AcWing 4244. 牛的比赛(双向建图BFS)

题目连接

https://www.acwing.com/problem/content/4247/

http://poj.org/problem?id=3660

思路

通过观察样例我们可以发现一个事情,如果说当前的一个点顺着当前建的边走下去加上逆着走下去能覆盖所有的点,那么这个点的一个排名就确定了,为什么呢?我们来思考一下这个操作的含义:

  • 顺着当前建立的边走那么就是找到排名比自己小的人数有多少
  • 逆着当前建立的边走那么就是找到排名比自己大的人数有多少

如果排名比自己大和比自己小的人数全部覆盖了,那么自己当前的排名也就能够知晓了,所以我们正向和反向建边,然后对于每一个点跑一个BFS就好啦,因为边权反正都是1

代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;

const int N = 1e2+10;

int n,m;
vector<int> E[2][N];
bool vis[N];

void bfs(int s,int loc){
	queue<int> que;
	que.push(s);
	while(!que.empty()){
		int t = que.front();
		que.pop();
		if(vis[t]) continue;
		vis[t] = true;
		for(int i = 0,l = E[loc][t].size();i < l; ++i){
			int j = E[loc][t][i];
			if(!vis[j]) que.push(j);
		}
	}
}

bool check(){
	for(int i = 1;i <= n; ++i) if(!vis[i]) return false;
	return true;
}


int main()
{
	cin>>n>>m;
	int u,v;
	for(int i = 1;i <= m; ++i){
		cin>>u>>v;
		E[0][u].push_back(v);
		E[1][v].push_back(u);
	}
	int ans = 0;
	for(int i = 1;i <= n; ++i) {
		memset(vis,false,sizeof vis);
		bfs(i,0);
		vis[i] = false;
		bfs(i,1);
		if(check()) ans++;
	}
	cout<<ans<<endl;
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MangataTS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值