BZOJ4424/CF19E Fairy(dfs樹+樹上差分)
阿新 • • 發佈:2018-10-29
stream 刪除 getc return color using lse dfs fine
即刪除一條邊使圖中不存在奇環。如果本身就是個二分圖當然任意一條邊都可以,先check一下。否則肯定要刪除在所有奇環的交上的邊。
考慮怎麽找這些邊。跑一遍dfs造出dfs樹,找出返祖邊構成的奇環。可以通過樹上差分標記奇環上的邊。
但是這顯然只包含了一部分奇環。註意到如果某條在奇環上的邊同時也在一個偶環上,一定可以找到一個不包含這條邊的奇環。並且圖中所有其他奇環都是由所找到的奇環加上偶環得到的,所以這就是充分的了。
數據中有重邊自環,自環特判一下比較舒服,而任意一條重邊都不可能在答案中(本身就是二分圖除外)。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<map> #include<cassert> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 1000010 map<int,int> f[N]; int n,m,p[N],t=-1,fa[N<<1],deep[N],cnt[2][N<<1],delta[2][N],tot; struct data{int to,nxt; }edge[N<<1]; void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;} int find(int x){returnfa[x]==x?x:fa[x]=find(fa[x]);} void dfs(int k,int from) { for (int i=p[k];~i;i=edge[i].nxt) if (edge[i].to!=from) if (deep[edge[i].to]&&deep[edge[i].to]<=deep[k]) { int op=deep[k]-deep[edge[i].to]&1; tot+=op^1;cnt[op][i]++; delta[op][k]++,delta[op][edge[i].to]--; } else if (!deep[edge[i].to]) { deep[edge[i].to]=deep[k]+1; dfs(edge[i].to,k); } } int Count(int op,int k,int from) { int s=0; for (int i=p[k];~i;i=edge[i].nxt) if (edge[i].to!=from&&!deep[edge[i].to]) { deep[edge[i].to]=deep[k]+1; int d=Count(op,edge[i].to,k); s+=d,cnt[op][i]+=d; } s+=delta[op][k]; return s; } int main() { #ifndef ONLINE_JUDGE freopen("bzoj4424.in","r",stdin); freopen("bzoj4424.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read(); for (int i=1;i<=n*2;i++) fa[i]=i; memset(p,255,sizeof(p)); bool flag=1;int sc=0; for (int i=1;i<=m;i++) { int x=read(),y=read(); if (x!=y) { f[x][y]++,f[y][x]++; addedge(x,y);if (x!=y) addedge(y,x); fa[find(x)]=find(y+n),fa[find(x+n)]=find(y); if (find(x)==find(y)) flag=0; } else sc=sc?m+1:i; } if (sc) { if (!flag||sc>m) {cout<<0;return 0;} cout<<1<<endl<<sc; return 0; } if (flag) {cout<<m<<endl;for (int i=1;i<=m;i++) printf("%d ",i);return 0;} for (int i=1;i<=n;i++) if (!deep[i]) deep[i]=1,dfs(i,0); memset(deep,0,sizeof(deep)); for (int i=1;i<=n;i++) if (!deep[i]) deep[i]=1,Count(0,i,0); memset(deep,0,sizeof(deep)); for (int i=1;i<=n;i++) if (!deep[i]) deep[i]=1,Count(1,i,0); m=0; for (int i=0;i<=t;i++) m+=(cnt[0][i]==tot)&&(cnt[1][i]==0)&&(f[edge[i^1].to][edge[i].to]==1); cout<<m<<endl;for (int i=0;i<=t;i++) if ((cnt[0][i]==tot)&&(cnt[1][i]==0)&&(f[edge[i^1].to][edge[i].to]==1)) printf("%d ",i/2+1); return 0; }
BZOJ4424/CF19E Fairy(dfs樹+樹上差分)