POJ - 2421 Constructing Roads (kruskal)

给你一个N个顶点的邻接矩阵形式的无向图,然后给你M个已经修好的路。问最后把所有村庄连接好的最小花费
思路:我们知道所给出的m条路已经修好即是两个村庄之间的距离被更改为0,顺便熟悉 kruskal算法 ,这里便用了。

我们使用 并查集 来表示边集合,然后记录所有的边信息 ,进行一次 sort 排序,如果不在一个集合就联立,否则继续

 

完整代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=100+10;//点数
const int maxm=10000+10;//边数
int pre[maxn];
struct Edge{
    int u,v,w;
}edge[maxm];
int top; 
int cnt;
int ans;

void addedge(int u,int v,int w){
    edge[top].u=u;
    edge[top].v=v;
    edge[top++].w=w;
} 
bool cmp(Edge a,Edge b) {
    return a.w<b.w; 
}
int find(int x)
{
    if(x!=pre[x]) return pre[x] = find(pre[x]);
    else return pre[x];
}
bool unite(int x,int y){
    int fx = find(x);
    int fy = find(y);
    if(fx!=fy) {
        pre[fx] = fy;
        cnt++;    
        return true;
    }
    else return false;
}
int Kruskal(int n){
    sort(edge,edge+top,cmp);//一次性把所有的边都排了 
    int u,v,w;
    for(int i=0;i<top;i++){
        u=edge[i].u;   
        v=edge[i].v;   
        w=edge[i].w; 
        if(unite(u,v)){
            ans += w;    
        }
        if(cnt==n-1) break;
    }
    if(cnt<n-1) return -1;
    return ans;
}
void init(int n){
    memset(edge,0,sizeof(edge));
    for(int i=0;i<=n;i++)
        pre[i] = i;
    ans = top = cnt = 0;
} 
int main(){
    int n,m,w,a,b;
    while(cin>>n){
        init(n);
        top=cnt=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                cin>>w;
                addedge(i,j,w);
            }
        }
        cin>>m;
        for(int i=0;i<m;i++){
            cin>>a>>b;
            unite(a,b);
        }
        cout<<Kruskal(n)<<endl;
    }
    return 0;
}

 

posted @ 2019-08-05 16:00  Tianwell  阅读(102)  评论(0编辑  收藏  举报