CF 19E Fairy——树上差分
Posted narh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF 19E Fairy——树上差分相关的知识,希望对你有一定的参考价值。
题目:http://codeforces.com/contest/19/problem/E
去掉一条边,使无向图变成二分图。
该边应该被所有奇环经过,且不被偶环经过。
因为一条非树边一定只在一个环里。所以一条既被所有奇环经过又被偶环经过的边是树边。如果把它去掉,将无法处理包含它的那个偶环的非树边和包含它的某个奇环的非树边加上两段树边所构成的奇环。
找这样的边,弄一个边上的树上差分就行了。
可以模仿kruscal用并查集弄一个生成树。不过dfs其实也行。
注意图可能不连通。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e4+5; int n,m,c[N][2],fa[N],head[N],t[N<<1],next[N<<1],tot; int hd[N],xnt,col[N],cnt,pa[N],prbh,bh[N<<1],q[N],qnt; bool vis[N]; struct Ed{ int nxt,to,bh;Ed(int n=0,int t=0,int b=0):nxt(n),to(t),bh(b) {} }ed[N<<1]; int find(int a){return fa[a]==a?a:fa[a]=find(fa[a]);} void add(int x,int y,int b) { ed[++xnt]=Ed(hd[x],y,b);hd[x]=xnt; ed[++xnt]=Ed(hd[y],x,b);hd[y]=xnt; } void dfs(int cr,int f) { vis[cr]=1; for(int i=head[cr],v;i;i=next[i]) if(col[v=t[i]]) { int f0=find(v),d=(col[cr]==col[v]); if(d){cnt++;if(cnt==1)prbh=bh[i];} c[cr][d]++;c[v][d]++;c[f0][d]-=2; } for(int i=hd[cr];i;i=ed[i].nxt) if(ed[i].to!=f) { col[ed[i].to]=3-col[cr];dfs(ed[i].to,cr); } fa[cr]=f; } void dfsx(int cr,int f,int eb) { vis[cr]=1; for(int i=hd[cr],v;i;i=ed[i].nxt) if((v=ed[i].to)!=f) { dfsx(v,cr,ed[i].bh); c[cr][0]+=c[v][0];c[cr][1]+=c[v][1]; } if(c[cr][1]==cnt&&!c[cr][0])q[++qnt]=eb; } int main() { scanf("%d%d",&n,&m);int x,y; for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); if(find(x)!=find(y)) { add(x,y,i); fa[find(x)]=find(y); } else{ t[++tot]=y;next[tot]=head[x];head[x]=tot;bh[tot]=i; t[++tot]=x;next[tot]=head[y];head[y]=tot;bh[tot]=i; } } for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<=n;i++) if(!vis[i]) col[i]=1,dfs(i,0); if(!cnt) { printf("%d ",m); for(int i=1;i<=m;i++)printf("%d ",i);return 0; } if(cnt==1)q[++qnt]=prbh; memset(vis,0,sizeof vis); for(int i=1;i<=n;i++) if(!vis[i])dfsx(i,0,0); sort(q+1,q+qnt+1); printf("%d ",qnt); for(int i=1;i<=qnt;i++)printf("%d ",q[i]); return 0; }
以上是关于CF 19E Fairy——树上差分的主要内容,如果未能解决你的问题,请参考以下文章