PTA 08-图7 公路村村通
原题链接
现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。
输入格式:
输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。
输出格式:
输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−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
结尾无空行
输出样例:
12
结尾无空行
思路
(1)如果找cost中找不到最小的->不连通
v=FindMin();//cost中最小的min值的i
if(v==-1){//找不到最小的
return -1;
}
(2)如果最后结点个数不为N个->不连通
int cnt=0;
for(int i=0;i<NumberofVertex;i++){
if(cost[i]==0){
cnt++;
}
}
if(cnt<NumberofVertex){
return -1;//不能构成生成树
}
Code
#include<iostream>
#define MaxN 1001
#define INIFITE 10001
using namespace std;
int G[MaxN][MaxN];
int cost[MaxN];//记录是否被标记MST和与MST树的距离
int NumberofVertex,NumberofEdge;
void init(){
for(int i=0;i<NumberofVertex;i++){
cost[i]=0;//全都离树距离为0
for(int j=0;j<NumberofVertex;j++){
if(i!=j){
G[i][j]=INIFITE;
}else{
G[i][j]=0;
}
}
}
}
//在cost中找min值的i
int FindMin(){
int index=-1,minlen=INIFITE;
for(int i=0;i<NumberofVertex;i++){
if(cost[i]!=0&&cost[i]<minlen){
minlen=cost[i];
index=i;
}
}
return index;
}
//实现prim算法
int Prim(){
int sum=0;
cost[0]=0;//将顶点加入MST树
//将第一个顶点和相关的边存到dist中
for(int i=0;i<NumberofVertex;i++){
if(G[0][i]){//有边
cost[i]=G[0][i];//存到cost中
}
}
int v;
for(int i=1;i<NumberofVertex;i++){//还需要找N-1个顶点
v=FindMin();//cost中最小的min值的i
if(v==-1){//找不到最小的
return -1;
}
sum+=cost[v];
cost[v]=0;//加入MST树中
for(int i=1;i<NumberofVertex;i++){
if(G[v][i]&&cost[v]+G[v][i]<cost[i]){//相邻结点且花费更小
cost[i]=cost[v]+G[v][i];
}
}
}
int cnt=0;
for(int i=0;i<NumberofVertex;i++){
if(cost[i]==0){
cnt++;
}
}
if(cnt<NumberofVertex){
return -1;//不能构成生成树
}
return sum;
}
int main(){
scanf("%d %d",&NumberofVertex,&NumberofEdge);
if(NumberofEdge<NumberofVertex-1){//M<N-1
printf("-1");
return 0;
}
init();
for(int i=0;i<NumberofEdge;i++){
int v1,v2,price;
scanf("%d %d %d",&v1,&v2,&price);
G[v1-1][v2-1]=G[v2-1][v1-1]=price;
}
int res=Prim();
printf("%d",res);
return 0;
}