2 3 3 1 2 2 3 3 1 7 6 1 2 1 3 1 4 1 5 1 6 1 7
1 1 1 0 1 0 1 0 1
题意:给一个无向图,把这个图变成有向图,要求每个点的|入度-出度|<=1。如果有则输出每个边〈u , v 〉的状态(1:表示原输入的无向边为 <u , v > 。0:则原输入为<v , u >)。
解题:
直接进行搜索,对每个点进行出度和入度的判断,如果出度大,就先进行反向的搜索(每搜索一条边<u,v>就认为这是一条v到u的有向边),反之,进行正向搜索(每搜到一条边<u,v>认为这是一条u到v的有向边),一直搜索到找不到边能继续走为止。一定会找到满足条件的一组答案。
注意:
已经使用过的边为了防止再次被遍历,可以修改head,head[u] = edge[i].next
#include<stdio.h>
#include<string.h>
const int MAXN = 210005;
const int MAXM = 710005;
struct EDG{
int to,next;
int id,flag; //每条边的编号,flag=1表示当前边与输入的顺序一至,否则顺序相反
}edg[MAXM];
int eid,head[MAXN];
int in[MAXN],out[MAXN] , ans[MAXM];
void init()
{
eid=0;
memset(head , -1 ,sizeof(head));
memset(ans , -1 ,sizeof(ans));
memset(out , 0 , sizeof(out));
memset(in , 0 , sizeof(in));
}
void addEdg(int u,int v,int id)
{
edg[eid].to=v; edg[eid].next=head[u];
edg[eid].id=id; edg[eid].flag=1; head[u]=eid++;
edg[eid].to=u; edg[eid].next=head[v];
edg[eid].id=id; edg[eid].flag=0; head[v]=eid++;
}
// u -> v , 正着走
void outIn(int u)
{
int i , v;
while(head[u]!=-1){
i=head[u];
v=edg[i].to;
if(ans[edg[i].id]==-1){ //每条边只能走一次
ans[edg[i].id]=edg[i].flag;
out[u]++;
in[v]++;
head[u]=edg[i].next; //走完后直接可以
u=v;
}
else
head[u]=edg[i].next;
}
}
// u <- v,反着走
void inOut(int u)
{
int i , v;
while(head[u]!=-1){
i=head[u];
v=edg[i].to;
if(ans[edg[i].id]==-1){
ans[edg[i].id]=!edg[i].flag; //从u -> v 实则 v -> u
in[u]++;
out[v]++;
head[u]=edg[i].next;
u=v;
}
else
head[u]=edg[i].next;
}
}
int main()
{
int T,n,m,u,v;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
init();
for(int i=1; i<=m; i++){
scanf("%d%d",&u,&v);
addEdg(u , v ,i);
}
for(int u=1; u<=n; u++){
while(head[u]!=-1){
if(in[u]>=out[u])
outIn(u);
else
inOut(u);
}
}
for(int i=1; i<=m; i++)
printf("%d\n",ans[i]);
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 5348 MZL's endless loop(思想用的是深搜)经典
原文地址:http://blog.csdn.net/u010372095/article/details/47298019