运送游客—并查集


问题描述:

Mr. G. works as a tourist guide. His current assignment is to take some tourists from one city to another. Some two-way roads connect the cities. For each pair of neighboring cities there is a bus service that runs only between those two cities and uses the road that directly connects them. Each bus service has a limit on the maximum number of passengers it can carry. Mr. G. has a map showing the cities and the roads connecting them. He also has the information regarding each bus service. He understands that it may not always be possible for him to take all the tourists to the destination city in a single trip. For example, consider the following road map of 7 cities. The edges connecting the cities represent the roads and the number written on each edge indicates the passenger limit of the bus service that runs on that road.

 

 

 

Now, if he wants to take 99 tourists from city 1 to city 7, he will require at least 5 trips and the route he should take is : 1 - 2 - 4 - 7. But, Mr. G. finds it difficult to find the best route all by himself so that he may be able to take all the tourists to the destination city in minimum number of trips. So, he seeks your help.


样例输入:

7 10

1 2 30

1 3 15

1 4 10

2 4 25

2 5 60

3 4 40

3 6 20

4 7 35

5 7 20

6 7 30

1 7 99

0 0



样例输出:

Scenario #1 Minimum Number of Trips = 5


思路分析:

题目大意:导游带着游客从一个城市到另一个城市,每条道路有人数限制,问把所有人送到目的地的最小次数。

我们要想次数最少,那每次运输的人要尽可能的大,所以我们先按照运输人数从大到小排序。在用并查集将两个城市点联通,直到找到了目的地。


解决方案:

#include "stdio.h"
#include "string.h"
#include "algorithm"
using namespace std;
int f[1100],n,m;
struct note
{
	int x, y,z;
}t[11000];
bool cmp(note m,note n)
{
	return m.z>n.z;
}//排序 
void init()
{
	int i;
	for(i=1;i<=n;i++)
	f[i]=i;
	return;
}//初始化 
int find(int u)
{
	if(f[u]==u)
	return u;
	else
	return find(f[u]);
}//寻找结点 
void merge(int u,int v)
{
	int t1,t2;
	t1=find(u);
	t2=find(v);
	if(t1!=t2)
	{
	   f[t1]=t2;
	}
	return;
}//连接两个点 
int main ()
{
	int i,j,sum,g=1;
  	while(~scanf("%d%d",&n,&m)&&n!=0&&m!=0)
  	{
  		sum=0;
  		for(i=1;i<=m;i++)
  		{
		  scanf("%d%d%d",&t[i].x,&t[i].y,&t[i].z);
	    }	
		int s1,s2,s3;
		scanf("%d%d%d",&s1,&s2,&s3);
	    sort(t+1,t+m+1,cmp);
	    init();
	    sum=0;
	    for(i=1;i<=m;i++)
	    {
		  merge(t[i].x,t[i].y);
		  //联通每两个城市 
		  if(find(s1)==find(s2))//找到了目的城市 
		  {
		    sum=sum+t[i].z;
            break;
          }
        }
        int ans;
		ans=s3/(sum-1);
		//因为给的是人数限制,要把导游这个减去,用游客数除以一次运输的游客数
		//才能得到次数 
		if(s3%(sum-1))//如果不能整除,剩下的还要在运一次 
		ans++;
		printf("Scenario #%d\n",g++);
		printf("Minimum Number of Trips = %d\n\n",ans);
	  }
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值