图算法专题(三)最小生成树

一、prim算法

问题:畅通工程

某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。

Input:测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
当N为0时,输入结束,该用例不被处理。

Output:对每个测试用例,在1行里输出最小的公路总长度。

Sample Input:

3
1 2 1
1 3 2
2 3 4
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
0

Sample Output

3
5

 代码:

#include <cstdio>
#include <iostream>
#include <cstring>

using namespace std;
const int INF=0x3f3f3f3f;
int G[100][100],d[100];
bool vis[100];
int n,m;
int x,y,z;
void prim();
int main(){
    while(cin>>n){
        if(n==0){
            break;
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(i==j){
                    G[i][j]=0;
                }else{
                    G[i][j]=INF;
                }
            }
        }
        m=n*(n-1)/2;
        for(int i=1;i<=m;i++){
            cin>>x>>y>>z;
            if(G[x][y]>z){
                G[x][y]=z;
                G[y][x]=z;
            }
        }
        prim();
    }
    return 0;
}

void prim(){
    for(int i=1;i<=n;i++){
        d[i] = INF;
        vis[i] = false;
    }
    d[1] = 0;
    for(int i=1;i<=n;i++){
        int u=-1,MIN=INF;
        for(int j=1;j<=n;j++){
            if(vis[j]==false&&d[j]<MIN){
                u = j;
                MIN = d[j];
            }
        }
        if(u==-1){
            break;
        }
        vis[u]=true;
        for(int v=1;v<=n;v++){
            if(vis[v]==false&&G[u][v]<d[v]){
                d[v]=G[u][v];
            }
        }
    }
    int ans =0;
    for(int i=1;i<=n;i++){
        ans+=d[i];
    }
    cout<<ans<<endl;   
}

二、kruskal算法

 问题同畅通工程

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn=105;
int s[maxn],n,m;
struct Edge{
    int u,v,w;
}edge[maxn*maxn];
bool cmp(Edge a,Edge b){
    return a.w<b.w;
}

int Find(int x);
int Kruskal();

int main(){
    while(cin>>n){
        if(n==0){
            break;
        }
        m=n*(n-1)/2;
        for(int i=1;i<=m;i++){
            cin>>edge[i].u>>edge[i].v>>edge[i].w;
        }
        cout<<Kruskal()<<endl;
    }
    return 0;
}

int Find(int x){
    if(s[x]==x){
        return x;
    }
    return s[x]=Find(s[x]);
}

int Kruskal(){
    int ans = 0;
    for(int i=1;i<=n;i++){
        s[i] = i;
    }
    sort(edge+1,edge+1+m,cmp); 
    for(int i=1;i<=m;i++){
        int b = Find(edge[i].u);
        int c = Find(edge[i].v);
        if(b==c){
            continue;
        }
        s[c] = b;
        ans+=edge[i].w;
    }
    return ans;
}

猜你喜欢

转载自www.cnblogs.com/bijian/p/12357195.html