赞
踩
设 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
- #include<bits/stdc++.h>
- using namespace std;
- long long int n,m;
- const int N=1e6+10,M=N*2;
- int head[N],e[M],ne[M],idx;
- bool iscol[N];
- int color[N];
-
-
-
- //求原始二分图每个集合的点数 m n-m
- //可添加的最大边数 sum=m*(n-m)-现有的边数n-1
-
- void add(int a,int b)
- {
- e[idx]=b;
- ne[idx]=head[a];
- head[a]=idx;
- idx++;
- }
-
-
- int dfs(int u,int col)
- {
- iscol[u]=true;
- color[u]=col;
- if(col==1) m++;
- for(int i=head[u];i!=-1;i=ne[i])
- {
- int j=e[i];
- if(!iscol[j]) {
- if(!dfs(j,3-col)) return 0;
- }
- else if(color[j]==col) return 0;
- }
- return 1;
-
-
- }
-
- int main()
- {
- cin>>n;
- memset(head,-1,sizeof head);
- for(int i=1;i<=n-1;++i)
- {
- int a,b;
- cin>>a>>b;
- add(a,b);
- add(b,a);
- }
- int flag;
- for(int i=1;i<=n;++i)
- {
- if(!iscol[i]) color[i]=1,flag=dfs(i,1);
- if(!flag) break;
- }
- if(flag) cout<<m*(n-m)-(n-1)<<endl;
- else cout<<0;
-
- system("pause");
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。