/*
5-2 畅通工程之最低成本建设问题 (30分)
某地区经过对城镇交通状况的调查,得到现有城镇间快速道路的统计数据,并提出“畅通工程”的目标:使整个地区任何两个城镇间都可以实现快速交通(但不一定有直接的快速道路相连,只要互相间接通过快速路可达即可)。现得到城镇道路统计表,表中列出了有可能建设成快速路的若干条道路的成本,求畅通工程需要的最低成本。
输入格式:
输入的第一行给出城镇数目NN (1< N \le 10001<N≤1000)和候选道路数目M\le 3NM≤3N;随后的MM行,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号(从1编号到NN)以及该道路改建的预算成本。
输出格式:
输出畅通工程需要的最低成本。如果输入数据不足以保证畅通,则输出“Impossible”。
输入样例1:
6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3
输出样例1:
12
输入样例2:
5 4
1 2 1
2 3 2
3 1 3
4 5 4
输出样例2:
Impossible
*/
#include<stdio.h>
#include <stdlib.h> //qsort()头文件
struct Edge{
int S;
int E;
int L;
}edge[3003];
int far[1001];
int N,P;
int cmp(const void *a, const void *b)
{
Edge *c = (Edge *)a; //将指针void *a强制转换成(Edge *)a并赋给指针Edge *c
Edge *d = (Edge *)b; //将指针void *b强制转换成(Edge *)b并赋给指针Edge *d
return c->L - d->L; //由小到大排列
}
int Find(int x){
int i,k,r;
r = x;
while(far[r]>=0)//far[r]就是r指向的根节点
r = far[r];//跳出的时候,far[r]小于0说明没有根节点,说明她就是最根节点
k = x;
while(k != r){//让由x结点一直到最根节点中间的所有结点都指向最根节点
i = far[k];
far[k] = r;
k = i;
}
return r;
}
void Union(int S,int E){//将两个结点连接
int rS,rE;
int num;
rS = Find(S);
rE = Find(E);
num = far[rS] + far[rE];//最根结点的指向必定为负
if(far[rS]<far[rE]){//负的越多说明需要连接的越多,说明更适合做根结点
far[rE] = rS;
far[rS] = num;
}else{
far[rS] = rE;
far[rE] = num;
}
}
int Kruskal(){
int S,E;
int w = 0;
int cnt = 0;
for(int i=0;i<N;i++){//初始化
far[i] = -1;
}
//对edge数组的1---P号边进行排序
qsort(edge, P, sizeof(edge[0]), cmp);
for(int i=0;i<P;i++){//对前面排序后,这里每次都要选择最小,这也是贪心的思想
S = edge[i].S;//S和E代表了一条通路
E = edge[i].E;
if(Find(S)!= Find(E)){
w += edge[i].L;
Union(S,E);
cnt++;
if(cnt >= N-1)
break;
}
}
if(cnt<N-1)//如果进行的连通次数没有达到N-1,说明有的没通路
return -1;
else
return w;
}
int main(){
scanf("%d",&N);
scanf("%d",&P);
for(int i=0;i<P;i++){
int t;
scanf("%d",&t);
edge[i].S = t-1;
scanf("%d",&t);
edge[i].E = t-1;
scanf("%d",&t);
edge[i].L = t;
}
int result = Kruskal();
if(result == -1)
printf("Impossible");
else
printf("%d",result);
return 0;
}
Kruskal算法-畅通工程之最低成本建设问题.cpp
最新推荐文章于 2022-03-25 16:57:46 发布