[CF19E]Fairy
Posted slrslr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF19E]Fairy相关的知识,希望对你有一定的参考价值。
给定一张n个点m条边的无向图,求删除哪一条边后,能够确保构成一个二分图,输出所有可能
解法:我们知道二分图的性质是没有奇环,这道题我们也应该从这个方面入手来考虑。
如果没有奇环的话我们当然想怎么删就怎么删,毕竟两个偶环删一条边不会出来一个奇环
如果存在奇环,那么我们删边一定要删奇环上的边,而且这条边必须是所有奇环的并
还要考虑的是,如果这条边还属于某个偶环,删掉这条边后图中还会形成一个新的奇环,因此删除的边还不能属于偶环
这种关于返祖边的题目用树上差分来处理就可以
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define M 10010 5 using namespace std; 6 struct point{ 7 int from,to,next; 8 }e[M<<1]; 9 struct Link{ 10 int odd,even; 11 bool flag; 12 int from,to; 13 }link[M]; 14 int n,m,num,cnt,tot; 15 int head[M],odd[M],even[M],ans[M],deep[M]; 16 bool vis[M]; 17 void add(int from,int to) 18 { 19 e[num].next=head[from]; 20 e[num].from=from; 21 e[num].to=to; 22 head[from]=num++; 23 } 24 void dfs(int x) 25 { 26 vis[x]=true; 27 for(int i=head[x];~i;i=e[i].next) 28 { 29 int to=e[i].to; 30 if(!vis[to]) 31 { 32 link[i>>1].flag=true; 33 deep[to]=deep[x]+1;//树边 34 dfs(to); 35 } 36 } 37 } 38 void DFS(int x) 39 { 40 vis[x]=true; 41 for(int i=head[x];~i;i=e[i].next) 42 { 43 int to=e[i].to; 44 if(!vis[to])//树边 45 { 46 DFS(to); 47 odd[x]+=odd[to]; 48 even[x]+=even[to]; 49 link[i>>1].odd=odd[to]; 50 link[i>>1].even=even[to]; 51 } 52 } 53 } 54 int main() 55 { 56 memset(head,-1,sizeof(head)); 57 scanf("%d%d",&n,&m); 58 for(int i=0;i<m;i++) 59 { 60 scanf("%d%d",&link[i].from,&link[i].to); 61 add(link[i].from,link[i].to); 62 add(link[i].to,link[i].from); 63 } 64 for(int i=1;i<=n;i++) 65 if(!vis[i]) 66 { 67 deep[i]=1; 68 dfs(i); 69 } 70 for(int i=0;i<m;i++) 71 { 72 if(link[i].flag) continue; 73 int u=link[i].from,v=link[i].to; 74 if(deep[u]>deep[v]) swap(u,v);//u为祖先 75 if((deep[v]-deep[u])&1) even[u]--,even[v]++; 76 else odd[u]--,odd[v]++,link[i].odd++,tot++; 77 } 78 if(!tot) 79 { 80 printf("%d ",m); 81 for(int i=1;i<=m;i++) printf("%d ",i); 82 return 0; 83 } 84 memset(vis,0,sizeof(vis)); 85 for(int i=1;i<=n;i++) 86 if(!vis[i]) 87 DFS(i); 88 for(int i=0;i<m;i++) 89 { 90 if(link[i].flag) 91 { 92 if(!link[i].even&&link[i].odd==tot) ans[++cnt]=i+1;//是奇环的并且不在偶环上 93 } 94 else if(tot==1&&link[i].odd) ans[++cnt]=i+1;//如果只有一个奇环,奇环中的边都可删 95 } 96 printf("%d ",cnt); 97 for(int i=1;i<=cnt;i++) printf("%d ",ans[i]); 98 return 0; 99 }
以上是关于[CF19E]Fairy的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 4424: Cf19E Fairy && codeforces 19E. Fairy树形dp