计蒜客习题:穿越雷区
2018-03-19 15:09
288 查看
问题描述
蒜头君最近迷上了一款 RPG 游戏,这次他要去森林里的 n 个宝藏点收集宝藏,编号从 1 到 n。森林里有 m 条道路连接宝藏点,每条道路上都有数量不等的地雷,蒜头君想从中找出若干条道路,使得任意两个宝藏点都是连通的,这样蒜头君都能访问到每个宝藏点了。另外,由于遇到一个地雷,蒜头君会减少一定的血量。现在蒜头君知道了这 m 条道路上的地雷数,蒜头君希望挑选若干条道路,使得挑选出的道路,地雷数量之和尽可能小。
输入格式
第一行输入两个整数 n,m(1≤n≤30,000,1≤m≤50,000),表示森林里有 n个宝藏点,m 条道路。两个宝藏点之间可能会有多条道路。
接下来输入 m 行,每行输入三个整数 x,y,z(1≤x,y≤n,0≤z≤1,000),表示 x 和 y 之间有 z 个地雷。
输出格式
输出一行,输出一个整数。表示蒜头君挑出了若干条道路,使得任意两个宝藏点都是连通的,输出道路的地雷数量之和最小值。
样例输入
3 4
1 2 121
1 3 202
2 1 497
2 3 135
样例输出
256
AC代码
#include <iostream> #include <algorithm> #include <cstdio> using namespace std; int MAXN=30010; int MAXM=50010; struct edge { int u,v,w; }e[50010]; int dad[30010]; int n,m; int getdad(int i) { if(dad[i]==i)return dad[i]; return dad[i]=getdad(dad[i]); } bool cmp(edge a,edge b) { return a.w<b.w; } int main() { for(int i=0;i<=MAXN+5;i++) { dad[i]=i; } cin>>n>>m; for(int i=1;i<=m;i++) { int x,y,z; cin>>x>>y>>z; e[i].u=x; e[i].v=y; e[i].w=z; } sort(e+1,e+m+1,cmp); int rest=n; int ans=0; for(int i=1;i<=m&&rest>1;i++) { if(getdad(e[i].u)!=getdad(e[i].v)) { dad[getdad(e[i].u)]=getdad(e[i].v); ans+=e[i].w; } } cout<<ans; return 0; }
ad79