比赛(Floyd / dfs)

 第3题     比赛 查看测评数据信息

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

第一行包含两个整数 N,M。

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

输出格式

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

输入/输出例子1

输入:

5 5

4 3

4 2

3 2

1 2

2 5

输出:

2

样例解释

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

5 号奶牛输给了排在第 4 的 2 号奶牛,所以它的战斗力排名为 5。

其它奶牛不确定。

 

 

第一个思路是,找点的入度出度(遍历),如果入度+出度-1(减去自己)==n,那就可以确定

入度 => 这头奶牛被打败了(注意“被”字), 出度 => 这头奶牛打败了其它奶牛
N - 1 => 除了这只奶牛之外的其它奶牛;
#include <bits/stdc++.h>
using namespace std;

int n, m, t1, t2, vis[105], vis2[105], cnt=0, cnt2=0, ans=0;
vector<int>a[105], a1[105]; 
void dfs(int now)
{
	if (vis[now]==1) return ;
	vis[now]=1;
	cnt++;
	for (int i=0; i<a[now].size(); i++)
		dfs(a[now][i]);
}
void dfs2(int now)
{
	if (vis2[now]==1) return ;
	vis2[now]=1;
	cnt2++;
	for (int i=0; i<a1[now].size(); i++)
		dfs2(a1[now][i]);
}
int main()
{
	scanf("%d%d", &n, &m);
	for (int i=1; i<=m; i++)
	{
		scanf("%d%d", &t1, &t2);
		a[t1].push_back(t2);
		a1[t2].push_back(t1);
	}
	for (int i=1; i<=n; i++)
	{
		cnt=0, cnt2=0;
		memset(vis, 0, sizeof(vis));
		memset(vis2, 0, sizeof(vis2));
		dfs(i);
		dfs2(i);
		//printf("%d %d\n", cnt, cnt2);
		if (cnt+cnt2-1==n) ans++;	
	}
	printf("%d", ans);
	
	return 0;
} 

 

第二个思路是floyd

floyd不仅能求任意两点的最短路,还能求一个点能否到另一个点。

程序流程:

    先跑Floyd,(跑Floyd可以明确所有点之间的关系(即使是间接到达的))

    然后再统计每个点的入、出度,查每个点,假设符合上面说的式子,ans++
#include <bits/stdc++.h>
using namespace std;

const int N=1e3+5;
int n, m, u1, v1, dis[N][N], ans=0;//dis[x][y]表示x,y是否连通 
void flo()
{
	for (int k=1; k<=n; k++)
		for (int i=1; i<=n; i++)
			for (int j=1; j<=n; j++)
				dis[i][j]=dis[i][j] || (dis[i][k] && dis[k][j]); //核心,意思要么是dis[i][j]中间本来就联通,或者从i到k并且从k到j都联通,如果两种情况都不是,就不连通
	
}
int main()
{
	scanf("%d%d", &n, &m);
	for (int i=1; i<=m; i++)
	{
		scanf("%d%d", &u1, &v1);
		dis[u1][v1]=1; //输入时将dis[x][y]赋值为真
	}
	flo();
	
	for (int i=1; i<=n; i++)
	{
		int s=0;
		for (int j=1; j<=n; j++)
			if (dis[i][j] || dis[j][i]) s++;  //有相连
		
		if (s==n-1) ans++; //排除自身这个点
	}
	printf("%d", ans);
	return 0;
}

 

posted @ 2024-01-27 08:49  cn是大帅哥886  阅读(18)  评论(0编辑  收藏  举报