题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1967
一共只会有偶数个奇数度的点。因为每多一条边,总度数加2。
把奇数度的点之间连一条边,然后走欧拉回路。回溯的时候加边的意思是真正走过的边,应该走的是它的反向边。
printf 会超时?!用putchar 快很多!
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e5+5,M=4e5+5;//M开得更大些 int n,m,hd[N],xnt=1,nxt[M<<1],to[M<<1],du[N],sta[N],top; bool fx[M],vis[N],zg[M]; int rdn() { int ret=0;char ch=getchar(); while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); return ret; } void add(int x,int y) { to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt; to[++xnt]=x;nxt[xnt]=hd[y];hd[y]=xnt; du[x]++;du[y]++; } void dfs(int cr) { vis[cr]=1; for(int i=hd[cr],v;i;i=nxt[i]) if(!zg[i>>1]&&du[v=to[i]]>0) { du[cr]--;du[v]--;zg[i>>1]=1; if((i&1)==0) fx[i>>1]=1; dfs(v); } } int main() { n=rdn();m=rdn(); for(int i=1,x,y;i<=m;i++) { x=rdn();y=rdn(); add(x,y); } for(int i=1;i<=n;i++) if(du[i]&1) sta[++top]=i; for(int i=1;i<=top;i+=2) add(sta[i],sta[i+1]); for(int i=1;i<=n;i++) if(!vis[i]) dfs(i); printf("%d ",n-top); for(int i=1;i<=m;i++) putchar(fx[i]?'1':'0'); return 0; }