看到入度等于出度想到欧拉回路。
我们把边都变成无向边,有一个结论是偶数度的点都可以变成出入度相等的点,而奇数点的不行,感性理解分类讨论一下就知道是对的。
还有一个更好理解的结论是变成无向边后奇数点的个数一定只有偶数个,因为有一个奇数点就一定有另一个跟他对应。
那么我们把奇数点凑成对连边,这样奇数点也变成了偶数点。无向图中所有的点的度数为偶数就存在欧拉回路,于是我们就可以跑一遍欧拉回路途中判断边是否需要返向来得到方案。
卡常题T T(其实是我写太丑
#include<stdio.h> #include<iostream> #include<cstring> #include<cstdlib> using namespace std; const int maxn=1000010; struct poi{int x,too,pre,pos;}e[maxn<<1]; int n,m,x,y,cnt,tot,cntt; int d[maxn],p[maxn],last[maxn],flag[maxn<<1],v[maxn]; char buf[80000010],*ptr=buf-1; inline int read() { char c=*++ptr;int s=0,t=1; while(c<48||c>57)c=*++ptr; while(c>=48&&c<=57){s=s*10+c-'0';c=*++ptr;} return s*t; } inline void add(int x,int y,int z,int from){e[++tot].x=from;e[tot].too=y;e[tot].pos=z;e[tot].pre=last[x];last[x]=tot;} void dfs(int x) { v[x]=1; for(register int i=last[x];i;last[x]=i=e[i].pre) if(!flag[e[i].pos]) { if(e[i].x==x)flag[e[i].pos]=1; else flag[e[i].pos]=2; dfs(e[i].too); } } int main() { fread(buf,1,sizeof(buf),stdin); n=read();m=read(); for(register int i=1;i<=m;++i) { x=read();y=read(); if(x==y)continue; add(x,y,i,x);add(y,x,i,x); d[x]++;d[y]++; } for(register int i=1;i<=n;++i)if(d[i]&1)p[++cnt]=i; for(register int i=1;i<=cnt;i+=2)add(p[i],p[i+1],(i>>1)+m+1,p[i]),add(p[i+1],p[i],(i>>1)+m+1,p[i]); for(register int i=1;i<=n;++i)if(!v[i])dfs(i); printf("%d ",n-cnt); for(int i=1;i<=m;i++)if(flag[i]==1)putchar('0');else putchar('1'); }