https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2833
题意:n个城市,可以在城市建机场,也可以建道路,要让每个城市都拥有一个机场或者通过道路与有机场的城市相连 求最小花费。
题解:假想一个0号城市,在i城市建立机场就等效于在i城市和0城市之间建一条花费为建立机场费用的路,题目的要求就等效于所有城市(包括0城市)联通。所以只要建图的时候,每个点都与0号城市建立花费为a的路,然后跑一遍最小生成树就可以了。
代码:
#include <iostream>
#include <cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int p[100005];
int n,m,a;
struct node {
int u,v,w;
}e[1000005];
int finde(int x){
if(p[x]==x)return x;
return p[x]=finde(p[x]);
}
void unit(int x,int y){
x=finde(x);
y=finde(y);
p[x]=y;
}
bool same(int x,int y){
x=finde(x);
y=finde(y);
if(x==y)return true;
return false;
}
void in_it(){
int i;
for(i=0;i<=n;i++)p[i]=i;
}
bool cmp(node a,node b){
if(a.w==b.w)return a.u<b.u;//保证在花费相同时优先建机场
return a.w<b.w;
}
void kru(){
int i;
int ans=0,cnt=0;
sort(e,e+m,cmp);
for(i=0;i<m;i++){
if(same(e[i].u,e[i].v))continue;
if(e[i].u==0)cnt++;
unit(e[i].u,e[i].v);
ans+=e[i].w;
}
printf("%d %d\n",ans,cnt);
}
int main()
{
int t,i,icase=0;
scanf("%d",&t);
while(t--){
icase++;
scanf("%d%d%d",&n,&m,&a);
for(i=0;i<m;i++)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
for(i=1;i<=n;i++){//与建立机场等效的道路
e[m].u=0;
e[m].v=i;
e[m].w=a;
m++;
}
in_it();
printf("Case #%d: ",icase);
kru();
}
// cout << "Hello world!" << endl;
return 0;
}