POJ3660 AcWing4244 Cow Contest

POJ3660
AcWing4244

题目翻译

N 头奶牛,编号 1∼N,一起参加比赛。奶牛的战斗力两两不同。这些奶牛之间已经进行了 M 轮两两对决。
在对决中,战斗力高的奶牛一定会战胜战斗力低的奶牛。请问,通过上述 M轮对决的结果,可以确定多少头奶牛的具体战斗力排名。

输入格式

第一行包含两个整数 N,M。
接下来 M行,每行包含两个整数 a,b,表示奶牛 a 和奶牛 b之间进行了对决,并且奶牛 a战胜了奶牛 b。

输出格式

输出可以确定具体战斗力排名的奶牛数量。

数据范围

1 ≤ N ≤ 100 1≤N≤100 1N100
1 ≤ M ≤ 4500 1≤M≤4500 1M4500
数据保证合法。

输入样例:

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

输出样例:

2

样例解释

2号奶牛输给了 1,3,4号奶牛,战胜了 5号奶牛,可以确定它的战斗力排名为 4。5号奶牛输给了排在第 4 的2号奶牛,所以它的战斗力排名为 5。其它奶牛不确定。

题解:

这道题是传递闭包("有向“)的模板题。
传递闭包问题:在交际网络中,给定若干个元素和若干对二元关系,且关系具有传递性。”通过传递性推导出尽量多的元素之间的关系“的问题。
可以用Floyd算法解决该问题。
我们用邻接矩阵来存储奶牛之间的战斗力的大小关系。 d [ i ] [ j ] = 1 d[i][j] = 1 d[i][j]=1表示i号奶牛的战斗力强于j号奶牛。如果奶牛i的战斗力强于奶牛k,而奶牛k的战斗力强于奶牛j,我们可以推出奶牛i的战斗力强于奶牛j,因此该二元关系具有传递性。我们只需要这样状态转移:

d[i][j] |= d[i][k] & d[k][j];

最后我们只需要枚举每个奶牛(设该奶牛为i号)。对于任意的其他奶牛 j j j,都满足 d [ i ] [ j ] d[i][j] d[i][j] d [ j ] [ i ] d[j][i] d[j][i]有一个为1,则i号奶牛的排名确定。

代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 105;
int d[N][N];
int main(){
	int n, m, i, j, k, x, y, ans;
	bool flag;
	scanf("%d%d", &n, &m);
	for(i = 1; i <= m; i++){
		scanf("%d%d", &x, &y);
		d[x][y] = 1;
	}
	//传递闭包
	for(k = 1; k <= n; k++)
		for(i = 1; i <= n; i++)
			for(j = 1; j <= n; j++)
				d[i][j] |= d[i][k] & d[k][j];
	ans = 0;
	for(i = 1; i <= n; i++){
		flag = 1;
		for(j = 1; j <= n; j++){
			if(j != i && d[i][j] == 0 && d[j][i] == 0){
				flag = 0;
			}
		}
		if(flag)
			ans++;
	}
	printf("%d", ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值