WEEK6 作业 C - 掌握魔法の东东 I

C - 掌握魔法の东东 I

题目描述

东东在老家农村无聊,想种田。农田有 n 块,编号从 1~n。种田要灌溉
众所周知东东是一个魔法师,他可以消耗一定的 MP 在一块田上施展魔法,使得黄河之水天上来。他也可以消耗一定的 MP 在两块田的渠上建立传送门,使得这块田引用那块有水的田的水。 (1<=n<=3e2)
黄河之水天上来的消耗是 Wi,i 是农田编号 (1<=Wi<=1e5)
建立传送门的消耗是 Pij,i、j 是农田编号 (1<= Pij <=1e5, Pij = Pji, Pii =0)
东东为所有的田灌溉的最小消耗!

Input

第1行:一个数n
第2行到第n+1行:数wi
第n+2行到第2n+1行:矩阵即pij矩阵

Output

东东最小消耗的MP值

Sample Input

4
5
4
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0

Sample Output

9

题解

将每一块田看作一个点,两块田之间建立传送门相当于两个点之间有通路,消耗的mp值即为路径的权重。若只是把所有的田连在一起,则就是在n个点的图中找最小连通树的问题。
而黄河之水天上来的操作,则可以看作有一个源点0,有的点可以和0点相连。最后需要将所有的田和天上(n+1个点)连起来。
不管是水从天上来还是从其他田里来,都需要消耗MP值,把MP值看作路径的权。
使用kruskal算法,过程中使用了树形并查集的方法。
par数组存储的是属性并查集中一块田的父节点(顺着父节点往上找就能找到代表元)。total数组存储的是以i为代表元的一组田中边的权重之和(连通这些田需要的MP值)。

代码

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
struct edge{
	int u,v,w;
	bool operator<(const edge&e)const{
		return w>e.w;
	}
};
vector<edge> v;
int n;//有多少块田 
int total[400];
int par[400];
void init(){//初始化 
	for(int i=0;i<=n;i++){par[i]=i;total[i]=0;}
}
int find(int x){
	return (par[x]==x)?x:(par[x]=find(par[x]));
}
void unite(int x,int y,int w){
	x=find(x),y=find(y);
	if(x==y){return;}
	par[x]=y;
	total[y]=total[y]+total[x]+w;
}
int main(int argc, char** argv) {
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int w;
		scanf("%d",&w);
		v.push_back({0,i,w});
	} 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			int w;
			scanf("%d",&w);
			if(j>i){//一开始是等于,是不必要的操作 
				v.push_back({j,i,w});
			}
		}
	} 
	make_heap(v.begin(),v.end());
	init();//一开始忘了初始化 
	while(!v.empty()){
		edge e=v[0];//由0改为1 
		pop_heap(v.begin(), v.end());
		v.pop_back();
		unite(e.u,e.v,e.w);
	}
	printf("%d\n",total[find(0)]);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值