数据结构课程设计2022夏7-3 修建道路

N个村庄,从1到N编号,现在请您兴建一些路使得任何两个村庄彼此连通。我们称村庄A和B是连通的,当且仅当在A和B之间存在一条路,或者存在一个存在C,使得A和C之间有一条路,并且C和B是连通的。

已知在一些村庄之间已经有了一些路,您的工作是再兴建一些路,使得所有的村庄都是连通的,并且兴建的路的长度是最小的。

输入格式:

第一行是一个整数N(3<=N<=100),代表村庄的数目。后面的N行,第i行包含N个整数,这N个整数中的第j个整数是第i个村庄和第j个村庄之间的距离,距离值在[1,1000]之间。

然后是一个整数Q(0<=Q<=N*(N+1)/2)。后面给出Q行,每行包含两个整数a和b(1<=a<b<=N),表示在村庄a和b之间已经兴建了路。

输出格式:

输出一行仅有一个整数,表示为使所有的村庄连通需要新建公路的长度的最小值。

输入样例:

3
0 990 692
990 0 179
692 179 0
1
1 2
 

输出样例:

179
 
代码长度限制
16 KB
时间限制
1000 ms
内存限制
64 MB
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=100010,M=200010;
int fa[N],n;
struct edges{
    int u,v,d;
}e[M];
int cnt;
bool cmp(edges a,edges b){
    return a.d<b.d;
}
int find(int x){
    return fa[x]==x?fa[x]:fa[x]=find(fa[x]);
}
ll dijkstra(int m){
    ll res=0;
    int k=0;
    for(int i=0;i<cnt;i++){
        int u=e[i].u,v=e[i].v,d=e[i].d;
        int fu=find(u),fv=find(v);
        if(fu!=fv){
            res+=d;
            fa[fu]=fv;
            k++;
        }
    }
    
    return k==n-1-m?res:0x3f3f3f3f;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        fa[i]=i;
    }
    
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            int x;
            cin>>x;
            if(i>j){
                e[cnt++]={i,j,x};
            }
        }
    }
    int m;
    cin>>m;
    for(int i=0;i<m;i++){
        int u,v;
        cin>>u>>v;
        int fu=find(u),fv=find(v);
        if(fu!=fv){
            fa[fu]=fv;
        }
    }
    
    sort(e,e+cnt,cmp);
    ll res=dijkstra(m);
    if(res!=0x3f3f3f3f){
        cout<<res<<endl;
    }
    else{
        cout<<"impossible"<<endl;
    }
    return 0;
}

 

posted @ 2022-07-14 23:03  zrswheart  阅读(99)  评论(0编辑  收藏  举报