[关闭]
@ysner 2018-09-26T19:56:20.000000Z 字数 1736 阅读 1760

CF19E Fairy

图论 二分图 树上差分


题面

删去一条边,使整张图成为二分图。

解析

我一开始想通过一遍找出图中所有环来着。。。
显然一条边可以从属于多个环,因此一遍肯定找不全。

怎么办呢?
据说可以树上差分。
就是在过程中,把边看成点建在新图中,每次把扫到的前后两条边在新图中连起来。
然后在形成奇环的时候,在当前点标号,在对面那一边(不是自己来的那条)处标号。偶环反过来。
同时如果出现一个奇环,就
最后从下往上上传标记,若有边标号为,那就说明它只属于所有奇环,不属于偶环,符合题目要求。

好妙啊。
记得奇环个数为时要特判。

  1. #include<iostream>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. #define ll long long
  8. #define re register
  9. #define il inline
  10. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  11. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  12. using namespace std;
  13. const int N=5e5+100;
  14. int n,m,a[N],sta[N],top,w[N],in[N],pos[N],tot,lk[N];
  15. bool vis[N];
  16. struct Edge{int to,nxt,id;};
  17. struct dag
  18. {
  19. Edge e[N<<1];
  20. int h[N],cnt;
  21. il dag(){memset(h,-1,sizeof(h));cnt=0;}
  22. il void add(re int u,re int v,re int id)
  23. {
  24. e[++cnt]=(Edge){v,h[u],id};h[u]=cnt;
  25. e[++cnt]=(Edge){u,h[v],id};h[v]=cnt;
  26. }
  27. }A,B;
  28. il ll gi()
  29. {
  30. re ll x=0,t=1;
  31. re char ch=getchar();
  32. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  33. if(ch=='-') t=-1,ch=getchar();
  34. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  35. return x*t;
  36. }
  37. il void dfs(re int u,re int fa,re int las)
  38. {
  39. sta[++top]=u;pos[u]=top;vis[u]=1;
  40. for(re int i=A.h[u];i+1;i=A.e[i].nxt)
  41. {
  42. re int v=A.e[i].to,id=A.e[i].id;
  43. if(las==id) continue;
  44. if(!lk[id]) lk[id]=1,B.add(las,id,0);
  45. if(!pos[v]) in[v]=id,dfs(v,u,id);
  46. else if(vis[v])
  47. {
  48. if((pos[u]-pos[v])&1) --w[id],++w[in[v]];
  49. else ++w[id],--w[in[v]],++tot;
  50. }
  51. }
  52. vis[u]=0;--top;
  53. }
  54. il void dfs(re int u,re int fa)
  55. {
  56. for(re int i=B.h[u];i+1;i=B.e[i].nxt)
  57. {
  58. re int v=B.e[i].to;
  59. if(v==fa) continue;
  60. dfs(v,u);
  61. w[u]+=w[v];
  62. }
  63. if(w[u]==tot) sta[++top]=u;
  64. }
  65. int main()
  66. {
  67. n=gi();m=gi();
  68. fp(i,1,m)
  69. {
  70. re int u=gi(),v=gi();
  71. A.add(u,v,i);
  72. }
  73. fp(i,1,n) if(!pos[i]) dfs(i,0,0);
  74. top=0;dfs(0,-2);
  75. if(!tot) {printf("%d\n",m);fp(i,1,m) printf("%d ",i);puts("");return 0;}
  76. sort(sta+1,sta+1+top);
  77. printf("%d\n",top);
  78. fp(i,1,top) printf("%d ",sta[i]);puts("");
  79. return 0;
  80. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注