1380:分糖果

本文探讨了一种算法问题,即在给定的网络中,糖果从一个节点开始传递,直至所有节点吃完糖果所需的最短时间。问题通过构建图结构并运用广度优先搜索(BFS)算法解决,以确定糖果传递的最深路径长度,再结合糖果的消耗时间得出最终答案。

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

1380:分糖果(candy)

时间限制: 1000 ms         内存限制: 65536 KB
提交数: 2596     通过数: 695 
【题目描述】
童年的我们,将和朋友分享美好的事物作为自己的快乐。这天,C小朋友得到了Plenty of candies,将要把这些糖果分给要好的朋友们。已知糖果从一个人传给另一个人需要1 秒的时间,同一个小朋友不会重复接受糖果。由于糖果足够多,如果某时刻某小朋友接受了糖果,他会将糖果分成若干份,分给那些在他身旁且还没有得到糖果的小朋友们,而且自己会吃一些糖果。由于嘴馋,小朋友们等不及将糖果发完,会在得到糖果后边吃边发。每个小朋友从接受糖果到吃完糖果需要m秒的时间。那么,如果第一秒C小朋友开始发糖,第多少秒所有小朋友都吃完了糖呢?

【输入】
第一行为三个数n、p、c,为小朋友数、关系数和C小朋友的编号。

第二行为一个数m,表示小朋友吃糖的时间。

下面p行每行两个整数,表示某两个小朋友在彼此身旁。

【输出】
一个数,为所有小朋友都吃完了糖的时间。

【输入样例】
4 3 1
2
1 2
2 3
1 4
【输出样例】
5
【提示】
【样例解释】

第一秒,糖在1手上。第二秒,糖传到了2、3的手中。第三秒,糖传到了4的手中,此时1吃完了。第四秒,2、3吃完了。第五秒,4吃完了。所以答案是5。

【限制】

40%的数据满足:1≤n≤100

60%的数据满足:1≤n≤1000

100%的数据满足:1≤n≤100000

m≤n*(n-1)/2,不会有同一个关系被描述多次的情况。

【来源】

No

此题可归纳为求树的深度,故可用bfs

	# include<iostream>
	# include<vector>
	# include<cstring>
	# include<queue>
	# define inf 0x3f3f3f3f
	using namespace std;
	 int n,m,c,t;
	const int maxn=100000+5;
	struct edge{
		int from;    //一个边的起始起点下标 
		int to;   //一个边的终止起点下标 
	   	//int dis;  //边的权值 
	   	edge(int u,int v):from(u),to(v)
	   	{
		   }
		   edge()
		   {
		   }
	};
	vector<int > g[maxn];
	vector<edge> edges;//存放边
	//int pre[maxn];
	int d[maxn];
	bool vis[maxn]; 
	void init()
	{
		for(int i=0;i<n;i++)
		   g[i].clear();
		edges.clear();
	}
	void read_graph()
	{  
	     init();
		for(int i=0;i<m;i++)
		{
			int u,v;
			cin>>u>>v;  
			u--;v--;
			edge e(u,v);
			edge ee(v,u);
			edges.push_back(e);
			int m=edges.size()-1;  //边的序号,下标从0开始故要-1 
			g[e.from].push_back(m);
			edges.push_back(ee);
			g[ee.from].push_back(m+1);  //此处出问题,没有将m+1,已改过; 
		}
	}
	int ans;
	void bfs(int s)
	{
		queue<int> q;
		memset(vis,0,sizeof(vis));
		for(int i=0;i<n;i++)
		 {
		 	d[i]=inf;
		 }
		ans=d[s]=1;
		vis[s]=true;
		q.push(s);
		while(!q.empty())
		{
			int k=q.front();
			q.pop();
			for(int i=0;i<g[k].size();i++)  //遍历邻接表,找到k->i的边的编号, 
			{
				edge e=edges[g[k][i]];
				if(!vis[e.to]&&d[e.to]==inf)
				{
					d[e.to]=d[e.from]+1;
					ans=max(ans,d[e.to]);
					q.push(e.to);
					vis[e.to]=true;
				}		
		   }
		}
		
	}
	int main()
	{
		cin>>n>>m>>c>>t;
		read_graph();
		bfs(c-1);
		cout<<ans+t<<endl;
		return 0;
	 }
# include<iostream>
# include<vector>
# include<cstring>
# include<queue>
# define inf 0x3f3f3f3f
using namespace std;
 int n,m,c,t;
const int maxn=100000+5;

vector<int > g[maxn];
//vector<edge> edges;//存放边
//int pre[maxn];
int d[maxn];
bool vis[maxn]; 
void init()
{
	for(int i=0;i<n;i++)
	   g[i].clear();
//	edges.clear();
}
void read_graph()
{  
     init();
	for(int i=0;i<m;i++)
	{
		int u,v;
		cin>>u>>v;
		g[u-1].push_back(v-1);
		g[v-1].push_back(u-1);
	}
}
int ans;
void bfs(int s)
{
	queue<int> q;
	memset(vis,0,sizeof(vis));
	for(int i=0;i<n;i++)
	 {
	 	d[i]=inf;
	 }
	ans=d[s]=1;
	vis[s]=true;
	q.push(s);
	while(!q.empty())
	{
		int k=q.front();
		q.pop();
		for(int i=0;i<g[k].size();i++)  //遍历邻接表,找到k->i的边的编号, 
		{
			int x=g[k][i];
			if(!vis[x])
			{
				d[x]=d[k]+1;
				ans=max(ans,d[x]);
				q.push(x);
				vis[x]=true;
			}		
	   }
	}
	
}
int main()
{
	cin>>n>>m>>c>>t;
	read_graph();
	bfs(c-1);
	cout<<ans+t<<endl;
	return 0;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值