1. 程式人生 > >51nod1967 路徑定向(歐拉回路+結論題)

51nod1967 路徑定向(歐拉回路+結論題)

void ++i col () view const stdio.h turn char

  看到入度等於出度想到歐拉回路。

  我們把邊都變成無向邊,有一個結論是偶數度的點都可以變成出入度相等的點,而奇數點的不行,感性理解分類討論一下就知道是對的。

  還有一個更好理解的結論是變成無向邊後奇數點的個數一定只有偶數個,因為有一個奇數點就一定有另一個跟他對應。

  那麽我們把奇數點湊成對連邊,這樣奇數點也變成了偶數點。無向圖中所有的點的度數為偶數就存在歐拉回路,於是我們就可以跑一遍歐拉回路途中判斷邊是否需要返向來得到方案。

  卡常題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",n-cnt); for(int i=1;i<=m;i++)if(flag[i]==1)putchar(0);else putchar(1); }
View Code

51nod1967 路徑定向(歐拉回路+結論題)