F. Milk Factory

本文详细解析了GDUT2020寒假训练排位赛二F题,介绍了使用深度优先搜索算法解决特定图论问题的方法,包括构建邻接矩阵、遍历图结构及判断可达性的过程。

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

GDUT 2020寒假训练 排位赛二 F

原题链接

题目

原题截图
The milk business is booming! Farmer John’s milk processing factory consists of N processing stations, conveniently numbered 1…N (1≤N≤100), and N−1 walkways, each connecting some pair of stations. (Walkways are expensive, so Farmer John has elected to use the minimum number of walkways so that one can eventually reach any station starting from any other station). To try and improve efficiency, Farmer John installs a conveyor belt in each of its walkways. Unfortunately, he realizes too late that each conveyor belt only moves one way, so now travel along each walkway is only possible in a single direction! Now, it is no longer the case that one can travel from any station to any other station.

However, Farmer John thinks that all may not be lost, so long as there is at least one station i such that one can eventually travel to station i from every other station. Note that traveling to station i from another arbitrary station j may involve traveling through intermediate stations between i and j. Please help Farmer John figure out if such a station i exists.

Input
The first line contains an integer N, the number of processing stations. Each of the next N−1 lines contains two space-separated integers ai and bi with 1≤ai,bi≤N and ai≠bi. This indicates that there is a conveyor belt that moves from station ai to station bi, allowing travel only in the direction from ai to bi.

Output
If there exists a station i such that one can walk to station i from any other station, then output the minimal such i. Otherwise, output −1.

样例
input
3
1 2
3 2
output
2
题目大意

有n个点,和n-1对关系,表示可以从x走到y(单向),求是否存在一个编号最小的点i,使得从任意点出发都可以到达点i,若不存在则输出-1.

思路

之前的思路是并查集,对每一个关系进行合并操作,并将该集合的元素+1

fx=getfa(x);
fy=getfa(y);
if(fx!=fy)
{
	fa[fx]=fy;
	ans[fy]+=ans[fx]+1;
}

ans[i]表示以i为老大的集合的元素个数。
最后从1到n遍历ans数组,找到哪一个集合的元素个数为n-1就输出,都找不到就输出-1。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<memory.h>
using namespace std;
int fa[200];
int ans[200];
int getfa(int x)
{
	if(fa[x]==x)return x;
	else return fa[x]=getfa(fa[x]);	
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		fa[i]=i;
	}
	memset(ans,0,sizeof ans);
	for(int i=1;i<=n-1;i++)
	{
		int x,y;
		cin>>x>>y;
		int fx,fy;
		fx=getfa(x);
		fy=getfa(y);
		if(fx!=fy)
		{
			fa[fx]=fy;
			ans[fy]+=ans[fx]+1;
		}
	}
	for(int i=1;i<=n;i++)
	{
		//cout<<ans[i]<<" ";
		if(ans[i]==n-1)
		{
			cout<<i<<endl;
			return 0;
		}
	}
	cout<<-1<<endl;
	return 0;
}

乍一看感觉莫得问题,但是提交就wa。
后来发现,这个并查集在路径压缩的时候将单向边的信息丢失了,也就是同属于一个集合但是并不能通过单向边到达。
比如
一种情况
这种情况,按照这个并查集的思路,1 2 3 4 同属于一个集合,而当构建1–>2,3–>2,3–>4这样的关系,输出的是4
当构建1–>2,3–>4,3–>2这样的关系,输出的是2
然而,这种情况不满足题意,也就是不存在这样的点,使得所有点都能到达该点,也就是应该输出-1.
那么通过这个例子发现,这样的并查集忽略了点与点之间的单向边的关系。所以决定采取深搜的办法。
深搜
构建邻接矩阵,对每一个点进行dfs,并在dfs的过程中记录经过点的个数,当经过点的个数与所有的的总数-1相等时输出这个点。

最后代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<memory.h>
using namespace std;
bool mp[105][105];
int cnt=0;
int n;
void dfs(int x)
{
	for(int i=1;i<=n;i++)
	{
		if(mp[i][x]==1)
		{
			cnt++;
			dfs(i);
		}
	}
	return ;
}
int main()
{
	cin>>n;
	memset(mp,false,sizeof mp);
	for(int i=1;i<=n-1;i++)
	{
		int x,y;
		cin>>x>>y;
		mp[x][y]=1;
	}
	for(int i=1;i<=n;i++)
	{
		cnt=0;
		dfs(i);
		if(cnt==n-1)
		{
			cout<<i<<endl;
			return 0;
		}
	}
	cout<<-1<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值