Bootstrap

7-1 公路村村通 (30 分)(C语言版)

先说思路:
看题,使所以点互通,可以看出这使一个求最小生成树的问题。
两种方法:
方法一:Kruskal算法:加边。
方法二:Prim算法:加点。
【下面代码有两种,任选其一即可】

现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

输入格式:
输入数据包括城镇数目正整数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
/*方法一:Kruskal算法*/
/*
#include<stdio.h>
#include<stdlib.h>
#define MAXV 1010
#define MAXE 3030
#define INF 99999
typedef struct Enode{
    int v1;//顶点
    int v2;//邻接点
    int weight;//权值
}ENode;
ENode E[MAXE];
int vset[MAXV+1];//每个顶点的leader/祖先
void sort(ENode E[],int e)//冒泡排序:把e条边按权值从小到大排序
{
    int i,j;
    ENode t;
    for(i=1;i<e;i++){
        for(j=0;j<e-i;j++){
            if(E[j+1].weight<E[j].weight){
                t=E[j+1];
                E[j+1]=E[j];
                E[j]=t;
            }
        }
    }
}

void Kruskal(ENode E[],int n,int e)
{

    int p1,p2,leader1,leader2;
    int count,sum=0;//边数、权值和
    int i,j;
    
    //核心算法
    for(i=1;i<n+1;i++)vset[i]=i;//初始化:祖先是它自己
    count=0;j=0;
    while(j<e){
        p1=E[j].v1;p2=E[j].v2;//取每条边对应的两个顶点
        leader1=vset[p1];leader2=vset[p2];//取其祖先
        if(leader1!=leader2){
            sum +=E[j].weight;
            count++;
            if(count>=n-1)break;//最小生成树:n个顶点,n-1条边
            for(i=1;i<=n;i++){
                if(vset[i]==leader2)vset[i]=leader1;
            }
        }j++;
    }
    
    //输出
    if(count==n-1)printf("%d\n",sum);
    else printf("-1\n");
}


int main()
{
    int n,e;
    int i;
    
    scanf("%d %d",&n,&e);
    for(i=0;i<e;i++){
        scanf("%d %d %d\n",&E[i].v1,&E[i].v2,&E[i].weight);
    }
    
    sort(E,e);
    Kruskal(E,n,e);
    return 0;
}*/

/*方法二:Prim算法*/
#include<stdio.h>
#include<stdlib.h>
#define MAXV 1010
#define INF 9999

typedef struct Gnode{
    int V[MAXV];//顶点集
    int E[MAXV][MAXV];//边集
    int n,e;//顶点数、边数
}GNode;


GNode *CreateGraph()
{
    GNode *G;
    G=(GNode*)malloc(sizeof(GNode));
    if(G==NULL)return NULL;
    int i,j,num1,num2,cost;
    
    scanf("%d %d",&(G->n),&(G->e));
    for(i=1;i<=G->n;i++)G->V[i]=i;//顶点集初始化
    for(i=1;i<=G->n;i++){//边集初始化
        for(j=1;j<=G->n;j++){
            G->E[i][j]=INF;
        }
    }
    for(i=1;i<=G->e;i++){
        scanf("%d %d %d",&num1,&num2,&cost);
        G->E[num1][num2]=cost;
        G->E[num2][num1]=cost;
    }
    return G;
}
void Prim(GNode *G)
{
    int lowcost[MAXV];
    int count=0,min,minId,sum=0;
    int i,j;
    
    for(j=1;j<=G->n;j++){
        lowcost[j]=G->E[1][j];
    }
    
    count++;lowcost[1]=0;
    while(count<G->n){
        min=INF;minId=1;
        for(i=1;i<=G->n;i++){
            if(lowcost[i]<min && lowcost[i]!=0){
                min=lowcost[i];
                minId=i;
            }
        }

        count++;lowcost[minId]=0;sum +=min;

        for(i=1;i<=G->n;i++){
            if(lowcost[i]!=0&& G->E[minId][i]<lowcost[i]){
                lowcost[i]=G->E[minId][i];
            }
        }
    }
    if(sum>INF)printf("-1");
    else printf("%d",sum);
}
int main()
{
    GNode *G;
    G=CreateGraph();
    Prim(G);
    return 0;
}




;