乱搞题...第一直觉是混合图的欧拉通路,但是感觉并没有多大关系。最终AC的做法是不断的寻找欧拉通路,然后给边标号。所有边访问了一遍,所有点访问了一遍,效率是o(n+m)。不存在-1的情况。
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<algorithm> using namespace std; const int maxn=100000; int n,m; struct Edge { int from,to; int ans; int flag; } edge[3*maxn+10]; vector<int> G[maxn+10]; int tot[maxn+10]; int Ru[maxn+10]; int Ch[maxn+10]; int St[maxn+10]; void dfs(int now,int x) { for(int i=St[now]; i<G[now].size(); i++) { Edge &e=edge[G[now][i]]; if(!e.flag)//这条边没走过 { St[now]=i+1; if(x==1) { if(e.from==now) { e.ans=1; e.flag=1; tot[e.from]--; tot[e.to]--; Ch[e.from]++; Ru[e.to]++; dfs(e.to,x); return; } else if(e.to==now) { e.ans=0; e.flag=1; tot[e.from]--; tot[e.to]--; Ch[e.to]++; Ru[e.from]++; dfs(e.from,x); return; } } else if(x==0) { if(e.to==now) { e.ans=1; e.flag=1; tot[e.from]--; tot[e.to]--; Ru[e.to]++; Ch[e.from]++; dfs(e.from,x); return; } else if(e.from==now) { e.ans=0; e.flag=1; tot[e.from]--; tot[e.to]--; Ru[e.from]++; Ch[e.to]++; dfs(e.to,x); return; } } } } } int main() { int T; scanf("%d",&T); for(int y=1; y<=T; y++) { scanf("%d%d",&n,&m); for(int i=0; i<=n; i++) G[i].clear(); memset(tot,0,sizeof(tot)); memset(Ru,0,sizeof(Ru)); memset(Ch,0,sizeof(Ch)); memset(St,0,sizeof(St)); for(int i=1; i<=m; i++) { scanf("%d%d",&edge[i].from,&edge[i].to); if(edge[i].from==edge[i].to) { edge[i].ans=1; continue; } edge[i].flag=0; G[edge[i].from].push_back(i); G[edge[i].to].push_back(i); tot[edge[i].from]++; tot[edge[i].to]++; } for(int i=1; i<=n; i++) { while(tot[i]) { if(Ru[i]>=Ch[i]) dfs(i,1); else dfs(i,0); } } for(int i=1; i<=m; i++) printf("%d ",edge[i].ans); } return 0; }