CF19 E Fairy——树上差分
Posted zinn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF19 E Fairy——树上差分相关的知识,希望对你有一定的参考价值。
题目:http://codeforces.com/contest/19/problem/E
先把图连成一棵树,然后对于每条非树边,判断它是在奇环中还是偶环中;
把环上的点打上相应的差分标记,并记录有多少个奇环;
dfs 出来后判断,若没有奇环,那么所有边都可以删;
若有奇环 k 个,遍历边,在 k 个奇环中而不在偶环中的边可以删;
如果一条边既在奇环中又在偶环中,那么若删掉它,原来的一奇环一偶环会合并成一个大奇环,所以这种边不能删;
写、调了整整两小时,改了许多冗余的地方和错误的地方才终于A了,我这代码能力...
码力++!
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int const maxn=2e4+5; int n,m,fa[maxn],sf[maxn],sg[maxn],g[maxn],f[maxn],ans[maxn],ns; int col[maxn],hd[maxn],ct,cnt,qhd[maxn],numj; bool vis[maxn]; struct N{ int to,nxt,edge; N(int t=0,int n=0,int e=0):to(t),nxt(n),edge(e) {} }ed[maxn<<1],q[maxn]; struct T{ int ff,gg; T(int f=0,int g=0):ff(f),gg(g) {} }; inline 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*10+ch-‘0‘,ch=getchar(); return ret*f; } inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} inline void add(int x,int y,int e){ed[++ct]=N(y,hd[x],e); hd[x]=ct;} inline void ad(int x,int y,int e){q[++cnt]=N(y,qhd[x],e); qhd[x]=cnt;} inline void dfs2(int x,int pre) { vis[x]=1; col[x]=!col[pre]; for(register int i=qhd[x];i;i=q[i].nxt) { int u=q[i].to; if(!vis[u])continue; int lca=find(u); if(col[u]==col[x]) { // f[u]++,f[i]++,f[pr[lca]]-=2,numj++; f[u]++,f[x]++,f[lca]-=2,numj++; sf[q[i].edge]=1; } else { // g[u]++,g[i]++,g[pr[lca]]-=2,numo++; g[u]++,g[x]++,g[lca]-=2; } } for(register int i=hd[x],u;i;i=ed[i].nxt) if((u=ed[i].to)!=pre)dfs2(u,x); fa[x]=pre; } inline T dfs3(int x,int pre) { int smf=f[x],smg=g[x]; vis[x]=1;//smf,smg!=0!!! for(register int i=hd[x],u;i;i=ed[i].nxt) { if((u=ed[i].to)==pre)continue; T k=dfs3(u,x);int e=ed[i].edge; sf[e]=k.ff; sg[e]=k.gg; smf+=k.ff; smg+=k.gg; } return T(smf,smg); } int main() { n=rd(); m=rd(); for(register int i=1;i<=n;i++)fa[i]=i; for(register int i=1,u,v;i<=m;i++) { u=rd(); v=rd(); if(find(u)!=find(v)) { fa[find(u)]=find(v); add(u,v,i); add(v,u,i); } else ad(u,v,i),ad(v,u,i); } for(register int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<=n;i++)if(!vis[i])dfs2(i,0);//不仅dfs(1,0) memset(vis,0,sizeof vis); if(!numj) { printf("%d ",m); for(int i=1;i<=m;i++)printf("%d ",i); return 0; } for(int i=1;i<=n;i++)if(!vis[i])dfs3(i,0); memset(vis,0,sizeof vis); for(register int i=1;i<=m;i++) if(sf[i]==numj&&!sg[i])ans[++ns]=i; printf("%d ",ns); sort(ans+1,ans+ns+1); for(register int i=1;i<=ns;i++)printf("%d ",ans[i]); return 0; }
以上是关于CF19 E Fairy——树上差分的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 4424: Cf19E Fairy && codeforces 19E. Fairy树形dp
树上差分CF 1076E. Vasya and a Tree