P2853 题解

56 阅读1分钟

题目链接

思路

一个牧场如果能被所有牛都访问到,就可以贡献一个答案。
最初想法是从每个有牛的牧场开始dfs,碰到有牛的牧场就“带上这只牛”,并把该牧场变成没有牛的牧场。但是这样做不好处理有环的情况,因为很难维护两次访问起点之间“带上了多少牛”。
退而求其次,碰到一只陌生的牛不带它,只将能够到达的牧场的访问次数加1,最后统计有多少牧场的访问次数为K。虽然比上一个算法慢一些,但是代码很好写。

代码

#include <bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
const int K=103,N=1E3+10,M=1E4+10;
using namespace std;
int k,n,m,tot,ans;
int vis[N],head[N],have[N],a[N];
struct Edge
{
	int nxt,to;
}e[M];
void add_edge(int u,int v)
{
	e[++tot].nxt=head[u];e[tot].to=v;head[u]=tot;
}
void dfs(int u)
{
	vis[u]=1;
	++a[u];
	for(int i=head[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(vis[v])
			continue;
		dfs(v);
	}
}
int main()
{
	scanf("%d%d%d",&k,&n,&m);
	rep(i,1,k)
	{
		scanf("%d",have+i);
	}
	int u,v;
	rep(i,1,m)
	{
		scanf("%d%d",&u,&v);
		add_edge(u,v);
	}
	rep(i,1,k)
	{
		memset(vis,0,sizeof(vis));
		dfs(have[i]);
	}
	rep(i,1,n)
	{
		if(a[i]==k)
			++ans;
	}
	cout<<ans<<endl;
}