[洛谷OJ] [USACO06DEC]牛的野餐Cow Picnic

解决一群奶牛在多个牧场间寻找共同可达聚会地点的问题。利用深度优先搜索算法遍历有向图,确定所有奶牛都能到达的牧场数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

The cows are having a picnic! Each of Farmer John’s K (1 ≤ K ≤ 100) cows is grazing in one of N (1 ≤ N ≤ 1,000) pastures, conveniently numbered 1…N. The pastures are connected by M (1 ≤ M ≤ 10,000) one-way paths (no path connects a pasture to itself).

The cows want to gather in the same pasture for their picnic, but (because of the one-way paths) some cows may only be able to get to some pastures. Help the cows out by figuring out how many pastures are reachable by all cows, and hence are possible picnic locations.

K(1≤K≤100)只奶牛分散在N(1≤N≤1000)个牧场.现在她们要集中起来进餐.牧场之间有M(1≤M≤10000)条有向路连接,而且不存在起点和终点相同的有向路.她们进餐的地点必须是所有奶牛都可到达的地方.那么,有多少这样的牧场呢?

输入输出格式
输入格式:

Line 1: Three space-separated integers, respectively: K, N, and M

第一行:三个整数K , N , M

Lines 2..K+1: Line i+1 contains a single integer (1..N) which is the number of the pasture in which cow i is grazing.

第2至K+1行:第i+1行包含一个整数(1到N之间),表示第i号奶牛所在的牧场

Lines K+2..M+K+1: Each line contains two space-separated integers, respectively A and B (both 1..N and A != B), representing a one-way path from pasture A to pasture B.

第K+2至第M+K+1行,每行两个正整数A,B 。 表示从A到B有一条单向边。

输出格式:

Line 1: The single integer that is the number of pastures that are reachable by all cows via the one-way paths.

输出符合题意的牧场数量

输入输出样例
输入样例#1:

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

输出样例#1:

2

题解:
我的方法是对于每只奶牛对整张图遍历,把走过的点上的计数器+1
,对于每个点,如果这个点的计数器上的数字等于K,则表示这个点所有的奶牛都能走到。为了方便写出,我选用深度优先遍历的方法。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define LiangJiaJun main
using namespace std;
int n,m,k;
int ne,h[1004];
struct edge{int to,next;}e[20004];
int cow[104],nob[1004];
bool vis[1004];
void insert(int u,int v){e[++ne].to = v; e[ne].next = h[u]; h[u] = ne;}
void dfs(int x){
     vis[x]=1;
     nob[x]++;
     for(int i=h[x];i;i=e[i].next){
         if(vis[e[i].to])continue;
         dfs(e[i].to);
     }
}
int LiangJiaJun (){
    scanf("%d%d%d",&k,&n,&m);
    for(int i=1;i<=k;i++)scanf("%d",&cow[i]);
    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        insert(u,v);
    }
    for(int i=1;i<=k;i++){
        memset(vis,0,sizeof(vis));
        dfs(cow[i]);
    }
    int ans=0;
    for(int i=1;i<=n;i++)if(nob[i]==k)++ans;
    printf("%d\n",ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值