更新:突然想明白了,本题不可以用并查集来做。
我原来的思路是,比如通过并查集得到3个集合,每个集合的元素个数分别是7,8,9那么最终无法判断的个数就是7*8+7*9+8*9。但是并查集只能判断他们是否属于同一个集合,而不能判断一个集合内部的每两个元素之间是否有输赢关系。比如输入1 2和1 3,由并查集可以得到123属于同一个集合,而不能判断2号和3号之间的输赢关系。而且本题抽象一下,可以看作是求每两个元素之间不能比较大小的个数。所以本题只能用传递闭包。借由本题也可以说明并查集与传递闭包的关系,读者可以仔细体会一下。
本题可以用传递闭包来做,也可以用并查集来做,用并查集做的思想就是算出每一个集合的元素个数,然后两两相乘,将乘积累加起来。但为什么一直WA,求大佬指导一二。
#include <stdio.h>
#include <string.h>int tree[501];
int num[501];int findRoot(int x)
{
if(tree[x] == x)
return x;
int tmp = findRoot(tree[x]);
tree[x] = tmp;
return tmp;
}int main()
{
int k, n, m;
scanf("%d", &k);
while(k--)
{
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++)
{
tree[i] = i;
num[i] = 1;
}
int a, b;
for(int i = 0; i < m; i++)
{
scanf("%d %d", &a, &b);
a = findRoot(a);
b = findRoot(b);
if(a != b)
{
tree[b] = a;
num[a] += num[b];
}
}
int tmp[250];
int id = 0;
bool flag =false;
for(int i = 1; i <= n; i++)
{
if(num[i] == 1)
continue;
if(num[i] == n)
{
flag = true;
break;
}
tmp[id++] = num[i];
}
if(flag)
printf("0\n");
else
{
int ans = 0;
for(int i = 0; i < id; i++)
for(int j = i+1; j < id; j++)
ans += tmp[i]*tmp[j];
printf("%d\n", ans);
}
}
return 0;
}