Week7 A TT的魔法猫

题目描述

众所周知,TT 有一只魔法猫。

这一天,TT 正在专心致志地玩《猫和老鼠》游戏,然而比赛还没开始,聪明的魔法猫便告诉了 TT 比赛的最终结果。TT 非常诧异,不仅诧异于他的小猫咪居然会说话,更诧异于这可爱的小不点为何有如此魔力?

魔法猫告诉 TT,它其实拥有一张游戏胜负表,上面有 N 个人以及 M 个胜负关系,每个胜负关系为 A B,表示 A 能胜过 B,且胜负关系具有传递性。即 A 胜过 B,B 胜过 C,则 A 也能胜过 C。

TT 不相信他的小猫咪什么比赛都能预测,因此他想知道有多少对选手的胜负无法预先得知,你能帮帮他吗?

Input

第一行给出数据组数。

每组数据第一行给出 N 和 M(N , M <= 500)。

接下来 M 行,每行给出 A B,表示 A 可以胜过 B。

Output

对于每一组数据,判断有多少场比赛的胜负不能预先得知。注意 (a, b) 与 (b, a) 等价,即每一个二元组只被计算一次。

Sample Input

3
3 3
1 2
1 3
2 3
3 2
1 2
2 3
4 2
1 2
3 4

Sample Output

0
0
4

思路

将选手想象成图中的点,将a战胜b转化为ab两点之间边长为1的有向边,即可应用Floyd算法进行求解。主要是将任意两点之间有向边的更新改为dis[i][j]=max(dis[i][j],dis[i][k]&dis[k][j]),这样当算法结束后,便考虑了所有点作为中间点对胜负关系的传递,即得到了所有胜负关系,若dis[i][j]与dis[j][i]均为零,则表示胜负不明,否则,胜负关系已明确。

代码

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 505;
int n, m, a1, b1, ans, temp;
int dis[N][N];

void Floyd()
{
	for (int k = 1; k <= n; k++)
		for (int i = 1; i <= n; i++)
			if (dis[i][k] != 0)
			{
				for (int j = 1; j <= n; j++)
					dis[i][j] = max(dis[i][j], dis[i][k] & dis[k][j]);
			}
}

int main()
{
	scanf_s("%d", &temp);
	for (int i = 0; i < temp; i++)
	{
		memset(dis, 0, sizeof(dis));
		scanf_s("%d%d", &n, &m);
		ans = 0;
		for (int j = 0; j < m; j++)
		{
			scanf_s("%d%d", &a1, &b1);
			dis[a1][b1] = 1;
		}
		Floyd();
		for (int k = 1; k <= n; k++)
			for (int l = 1; l <= n; l++)
				if (dis[k][l] == 0 && dis[l][k] == 0&&k!=l)
					ans++;
		ans /= 2;
		printf("%d\n", ans);
	}
    return 0; 
}
发布了32 篇原创文章 · 获赞 0 · 访问量 675

猜你喜欢

转载自blog.csdn.net/qq_43814559/article/details/105545036
今日推荐