题目描述
很久很久以前,有一个仙女叫做A。有一天一个少年B找到她,并且请求她预测他的未来。仙女看着她的水晶球,说这位少年不久将遇见世界上最美丽的公主,并且将迎娶她为妻。然后仙女在一张纸上画了n个点,并把它们分为几个板块,每个板块以一些点为始,另一些点为终。画完这幅画,仙女要求少年擦掉之上的一个板块。然后她尝试给每个点画上红色或蓝色,让纸上没有板块有和它的结尾颜色一样的点。如果她能做到,这个预言将会成真。B想邂逅世界上最美丽的公主,所以他想要你帮助他。找到所有能帮助他邂逅公主的板块。
输入输出格式:
输入格式:
输入文件的第一行有两个整数:n——点数;m:板块个数。
接下来的m行有板块的描述。每一个描述有两个整数,用空格隔开——v,u——各点的编号(index),由此板块连接。没有板块在描述中会被描述两次。
输出格式:
输出文件的第一行输出数字k——答案中板块的数量。输出文件的第二行输出k个数字,以空格隔开————每个板块的编号,升序排列。每个编号只应被输出一次。板块从1开始编号,以输入的顺序为序。
题解
因为二分图没有奇环,我们就把奇环删掉就行了。
实际上需要分情况讨论:
当没有奇环时,随便删掉一条边即可。
当只有一个奇环时,删掉这个奇环上没有被偶环覆盖的边就行(因为把一个奇环和一个偶环的公共边删去还是一个奇环)
当有多条奇环时,删掉被所有奇环覆盖的且不被偶环覆盖的边。
代码细节很多具体看代码
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 const int maxn=500000; 6 int n,m,sum,ans,cnt; 7 int f[maxn],to[maxn<<1],next[maxn<<1],book[maxn<<1],head[maxn],pa[maxn],pb[maxn],vis[maxn],dep[maxn]; 8 int fa[maxn][31],Log[maxn],pc[maxn],s1[maxn],s0[maxn],from[maxn],bok[maxn]; 9 inline void add(int a,int b){ 10 to[++cnt]=b; 11 next[cnt]=head[a]; 12 head[a]=cnt; 13 } 14 void dfs1(int x){ 15 vis[x]=1; 16 for(int i=head[x];i;i=next[i]) 17 if(!vis[to[i]]) 18 book[i]=1,fa[to[i]][0]=x,dep[to[i]]=dep[x]+1,from[to[i]]=(i>>1),dfs1(to[i]); 19 } 20 int lca(int u,int v){ 21 if(dep[u]<dep[v])swap(u,v); 22 for(int i=30;i>=0;i--){ 23 if(dep[fa[u][i]]>=dep[v])u=fa[u][i]; 24 } 25 if(u==v)return v; 26 for(int i=30;i>=0;i--){ 27 if(fa[u][i]!=fa[v][i]){ 28 u=fa[u][i];v=fa[v][i]; 29 } 30 } 31 return fa[u][0]; 32 } 33 void dfs2(int x){ 34 for(int i=head[x];i;i=next[i]) 35 if(book[i]) 36 dfs2(to[i]),s1[x]+=s1[to[i]],s0[x]+=s0[to[i]]; 37 } 38 int main() 39 { 40 scanf("%d%d",&n,&m); 41 cnt=1; 42 int i,j; 43 for(i=1;i<=m;i++){ 44 scanf("%d%d",&pa[i],&pb[i]);add(pa[i],pb[i]);add(pb[i],pa[i]); 45 } 46 for(i=1;i<=n;i++) if(!vis[i]) dep[i]=1,dfs1(i); 47 for(int i=1;i<=30;i++) 48 for(int j=1;j<=n;j++){ 49 fa[j][i]=fa[fa[j][i-1]][i-1]; 50 } 51 for(i=1;i<=m;i++) 52 if(!book[i*2]&&!book[i*2+1]){ 53 pc[i]=lca(pa[i],pb[i]); 54 if(!((dep[pa[i]]^dep[pb[i]])&1))sum++,s1[pa[i]]++,s1[pb[i]]++,s1[pc[i]]-=2; 55 else s0[pa[i]]++,s0[pb[i]]++,s0[pc[i]]-=2; 56 } 57 for(i=1;i<=n;i++)if(dep[i]==1)dfs2(i); 58 if(!sum){ 59 printf("%d\n",m); 60 for(i=1;i<=m;i++)printf("%d ",i); 61 return 0; 62 } 63 if(sum==1) 64 for(i=1;i<=m;i++) 65 if(!book[i*2]&&!book[i*2+1]&&!((dep[pa[i]]^dep[pb[i]])&1))bok[i]=1,ans++; 66 for(i=1;i<=n;i++) 67 if(s1[i]==sum&&!s0[i])bok[from[i]]=1,ans++; 68 printf("%d\n",ans); 69 for(i=1;i<=m;i++) 70 if(bok[i])printf("%d ",i); 71 return 0; 72 }