CQUPT第十三届ACM网赛 H. 活动图 题解

 

输入样例
6 7
3 1 4 1 5 9
1 2 7
1 3 11
2 3 13
3 4 1
3 6 19
4 5 20
5 6 1
输出样例
5

 我们需要走遍整张图,故求最小生成树即可,想复杂了。

因为我们需要拿完所有的金币且开局带的金币最少,显然只需要过路费对我们的限制最小,找到过路费最少且能走完所有的城市的路就ok了,用过路费当做两个城市的距离求最小生成树即可。

巧妙点在于如何存需要过路费的最大值,如下

#include<bits/stdc++.h>

using namespace std;

int city[100005];
int n,m;
int getMoney[100005];
int needMoney[100005];

struct road{
	
	int x;
	int y;
	int need;
	
}Roads[100005];

bool cmp( road a , road b ){
	return a.need<b.need;
}

int getF( int a ){
	return a==city[a]?a:city[a]=getF(city[a]); //并查集并且进行路径压缩。 
}

int main(){
	
	cin>>n>>m;//n个城市,m条路
	
	for ( int k = 1 ; k <= n ; ++k ){	
		scanf("%d",&getMoney[k]);
		city[k] = k;	//进过第N个城市获得的金币数,初始化并查集 
	}
	
	for ( int k = 0 ; k < m ; ++k )		scanf("%d%d%d",&Roads[k].x,&Roads[k].y,&Roads[k].need);	//输入所有路;
	
	sort( Roads , Roads + m , cmp ); 
	
	for ( int k = 0 ; k < m ; ++k ){
		
		int x = getF( Roads[k].x );
		int y = getF( Roads[k].y );
		
		if ( x == y )	continue;  //成环
		
		
		
		needMoney[x] = max( needMoney[x]  , Roads[k].need - getMoney[x] );
		needMoney[y] = max( needMoney[y]  , Roads[k].need - getMoney[y] );
		
		if ( needMoney[x] > needMoney[y] )
			 swap( x , y );
		//如果从x走到y比y走到x需要初始金额更多,那么选择小的一个
		//故我们交换xy,这时从x->y需要的金额较少 
		
		getMoney[x] += getMoney[y];
		//此时你走到x会获得的金币会累加,同时你need的Money也存入了x 
		
		
		city[y] = x; //连接两条路
		//注.这句话与 city[x] = y 不等价
		//因为你能获取的钱累加到了x上,但事实上你在x与y两点获取的钱是一样的,所以我们用city[y]=x指向
		//如果用 city[x] = y的话,那么你想取在y出得到的最多的钱也就变成了 needMoney[ getF( y ) ] = needMoney[y] != needMoney[x];   
	}
	
	cout<<needMoney[ getF(1) ]<<endl;
	//最终整个图被连成了一个树,所以getF(x) x可以为 1-n的任何数 
	
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值