1. 程式人生 > >CF19 E Fairy——樹上差分

CF19 E Fairy——樹上差分

namespace return http 多少 using bsp getchar 若有 har

題目: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\n",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\n",ns); sort(ans+1,ans+ns+1); for(register int i=1;i<=ns;i++)printf("%d ",ans[i]); return 0; }

CF19 E Fairy——樹上差分