题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1967
显然是欧拉回路问题,度数为奇数的点之间连边,跑欧拉回路就可以得到方案;
想一想不会有奇数个奇度数的点,否则总度数就是奇数,但一条边增加两个度,所以总度数一定是偶数;
一定注意奇度数的点之间连边时要 deg++ !还是把这个写在连边函数里比较靠谱...
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int const maxn=1e5+5,maxm=4e5+5; int n,m,hd[maxn],ct=1,to[maxm<<1],nxt[maxm<<1],deg[maxn],ans; bool vis[maxn],use[maxm],fx[maxm]; void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct; deg[y]++;}//deg! int rd() { int ret=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); return ret*f; } void dfs(int x) { vis[x]=1; for(int i=hd[x],u;i;i=nxt[i]) { if(use[i>>1]||!deg[u=to[i]])continue; deg[x]--; deg[u]--; use[i>>1]=1; if(i&1)fx[i>>1]=1;//反向边 dfs(u); } } int main() { n=rd(); m=rd(); for(int i=1,x,y;i<=m;i++) { x=rd(); y=rd(); add(x,y); add(y,x); } for(int i=1,pre=0;i<=n;i++) if(deg[i]%2==1) { ans++; if(pre)add(i,pre),add(pre,i),pre=0; else pre=i; } printf("%d ",n-ans); for(int i=1;i<=n;i++) if(!vis[i])dfs(i); for(int i=1;i<=m;i++)putchar(fx[i]?'0':'1');//路径是反向回来 return 0; }