题意:给你n个点,有n+1条边,现在要删除一些边(至少一条),最后这些点还是可以都联通。
分析: 要使n个点都联通,至少需要n-1条边,所以至多删除2条边。
枚举这两条边(或者唯一的一条边) 然后用并查集判断所有的点是否相连。
复杂度O(N^3);
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int Father[111];
int from[111];
int to[111];
int Find(int x)
{
return Father[x] == x ? x : Father[x] = Find(Father[x]);
}
void Union(int x, int y)
{
int xx = Find(x);
int yy = Find(y);
if (xx != yy)
{
Father[xx] = yy;
}
}
bool Judge(int n,int m,int x,int y)
{
for (int i = 1; i <= n; i++) Father[i] = i; //初始化
for (int i = 1; i <= m; i++)
{
if (i == x || i == y) continue; //这条边已经删掉了
Union(from[i], to[i]);
}
//判断所有的点是否相连
for (int i = 1; i <= n; i++)
{
int cur = Find(i);
if (cur != Find(1))
{
return false;
}
}
return true;
}
int main()
{
int TestCas;
scanf("%d", &TestCas);
while (TestCas--)
{
int n, m;
scanf("%d", &n);
m = n + 1;
for (int i = 1; i <= m; i++)
{
scanf("%d%d", &from[i], &to[i]);
}
//删除一条边
int ans = 0;
for (int i = 1; i <= m; i++)
{
if (Judge(n, m, i, -1) == true)
ans++;
}
for (int i = 1; i <= m; i++)
{
for (int j =i + 1; j <= m; j++)
{
if (Judge(n, m, i, j) == true)
{
ans++;
}
}
}
printf("%d\n", ans);
}
return 0;
}