问题描述
众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的:给出一张
n
个点
n+1
条边的无向图,你可以选择一些边(至少一条)删除。现在勇太想知道有多少种方案使得删除之后图依然联通。当然,这个问题对于萌萌哒六花来说实在是太难了,你可以帮帮她吗?
输入描述
第一行一个整数表示数据组数
T(T≤30)
。每组数据的第一行是一个整数
n(n≤100)
。接下来
n+1
行每行两个整数
u,v
表示图中的一条边。
输出描述
对每组数据输出一行一个整数表示答案。
输入样例
1
3
1 2
2 3
3 1
1 3
输出样例
9
------------------------------------
bestcoder官方解法:让 n 个点联通最少需要 n−1 条边,所以最多只能删除两条边,我们可以枚举删除的这两条边(或者唯一的一条边),然后暴力BFS判断连通性就好了。时间复杂度 O(n3)。
-------------------------------
分析:思路同官方解法,不同的是采用并查集判断连通性
#include<iostream>
using namespace std;
int u[105] = {0};
int v[105] = {0};
int f[105] = {0};
int n;
int sum ;
void init(){
for(int i = 0; i < n+1; i++){
f[i] = i;
}
}
int getf(int x){
if(f[x] == x) return x;
else {
f[x] = getf(f[x]);
return f[x];
}
}
void merge (int u,int v){
int t1,t2;
t1 = getf(u);
t2 = getf(v);
if(t1 != t2){
f[t2] = t1;
}
}
void solve (int x){//delete one edge
init();
for(int i = 0; i < n+1; i++){
if(i != x){
merge(u[i],v[i]);
}
}
int count = 0;
for(int i = 1; i < n+1; i++){// enumaration edge
if(f[i] == i) count++;
}
if(count == 1) sum++;
}
void solve2 (int x,int y){//delete two edge
init();
for(int i = 0; i < n+1; i++){
if(i != x&&i != y){
merge(u[i],v[i]);
}
}
int count = 0;
for(int i = 1; i < n+1; i++){// enumaration edge
if(f[i] == i) count++;
}
if(count == 1) sum++;
}
int main(){
int cas;
cin>>cas;
while(cas--){
cin>>n;
for(int i = 0 ; i < n+1; i++){
cin>>u[i]>>v[i];
}
sum = 0;
for(int i = 0; i < n+1; i++){
solve(i);
}
for(int i = 0; i < n+1; i++){
for(int j = i+1; j < n+1; j++){
solve2(i,j);
}
}
cout<<sum<<endl;
}
return 0;
}