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