当前位置:   article > 正文

Robocom-2022初赛-树与二分图

Robocom-2022初赛-树与二分图

设 G=(V,E) 是一个无向图,如果顶点集合 V 可分割为两个互不相交的子集 (A,B),并且每条边 (i,j)∈E 的两个端点 i 和 j 分别属于这两个不同的顶点子集,则称图 G 为一个二分图。

现在给定一棵树 T,要求选择树中两个没有边相连的结点 i 和 j,使得将无向边 (i,j) 加进 T 后能够构成二分图。你的任务是计算满足这个要求的选择方案有多少种。

输入格式:

输入第一行给出一个正整数 N (2≤N≤106),表示树中结点的个数。

接下来 N−1 行,每行给出树中一条边的两端结点编号,以空格分隔。结点编号从 1 开始。题目保证输入给出的是一棵树中所有的边。

输出格式:

在一行中输出方案数。注意:连接 (1,2) 和 (2,1) 视作同一个方案。

输入样例:

7
1 2
2 3
2 4
2 5
2 6
4 7

输出样例:

4


一、分析

1.求出给出图的二分两个集合的点数量,m和n-m,则可选方案为m*(m-n)-已有的边数(n-1)

2.如何求m:用染色法可以发现点会染成两中颜色,直接按颜色数

3.注意m为LL int ,否则答案部分WA

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. long long int n,m;
  4. const int N=1e6+10,M=N*2;
  5. int head[N],e[M],ne[M],idx;
  6. bool iscol[N];
  7. int color[N];
  8. //求原始二分图每个集合的点数 m n-m
  9. //可添加的最大边数 sum=m*(n-m)-现有的边数n-1
  10. void add(int a,int b)
  11. {
  12. e[idx]=b;
  13. ne[idx]=head[a];
  14. head[a]=idx;
  15. idx++;
  16. }
  17. int dfs(int u,int col)
  18. {
  19. iscol[u]=true;
  20. color[u]=col;
  21. if(col==1) m++;
  22. for(int i=head[u];i!=-1;i=ne[i])
  23. {
  24. int j=e[i];
  25. if(!iscol[j]) {
  26. if(!dfs(j,3-col)) return 0;
  27. }
  28. else if(color[j]==col) return 0;
  29. }
  30. return 1;
  31. }
  32. int main()
  33. {
  34. cin>>n;
  35. memset(head,-1,sizeof head);
  36. for(int i=1;i<=n-1;++i)
  37. {
  38. int a,b;
  39. cin>>a>>b;
  40. add(a,b);
  41. add(b,a);
  42. }
  43. int flag;
  44. for(int i=1;i<=n;++i)
  45. {
  46. if(!iscol[i]) color[i]=1,flag=dfs(i,1);
  47. if(!flag) break;
  48. }
  49. if(flag) cout<<m*(n-m)-(n-1)<<endl;
  50. else cout<<0;
  51. system("pause");
  52. return 0;
  53. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/900979
推荐阅读
相关标签
  

闽ICP备14008679号