PTA 修建道路

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

#include<bits/stdc++.h>
using namespace std;

const int MAXE = 10010,MAXV = 101,INF = INT_MAX;
int g[MAXV][MAXV],f[MAXV],n,cnt;

struct edge{
    int u,v,w;
}e[MAXE];
bool cmp(edge a,edge b){
    return a.w<b.w;
}
int find(int x){
    if(x!=f[x])    f[x] = find(f[x]);
    return f[x];
}
int krus(){
    int ans = 0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(g[i][j]){//转化为结构体
                e[cnt].u = i;
                e[cnt].v = j;
                e[cnt].w = g[i][j];
                cnt++;
            }
        }
    }
    sort(e,e+cnt,cmp);
    for(int i=0;i<cnt;i++){
        if(find(e[i].u)!=find(e[i].v)&&g[e[i].u][e[i].v]!=0){
            f[find(e[i].u)] = e[i].v;
            ans += e[i].w;
        }
    }
    return ans;
}
int main()
{
    cin>>n;
    for(int i=1; i<=n; i++)    f[i] = i;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            cin>>g[i][j];
    int q;    cin>>q;
    while(q--){
        int a,b;    cin>>a>>b;
        f[find(a)] = find(b);
        g[a][b] = g[b][a] = 0;
    }
    cout<<krus();

    return 0;
}
// const int N = 101,INF = INT_MAX;
// int g[N][N],d[N],n;
// bool st[N];
// int prim(int s){
//     fill(d,d+n,INF);
//     d[s] = 0;
//     int ans = 0;
//     for(int i=1; i<=n; i++){
//         int u = -1,MIN = INF;
//         for(int j=1; j<=n; j++){
//             if(!st[j] && d[j]<MIN){
//                 u = j;
//                 MIN = d[j];
//             }
//         }
//         if(u==-1)    return -1;
//         st[u] = true;
//         ans += d[u];
//         for(int v=1; v<=n; v++){
//             if(!st[v] && g[u][v]<d[v])
//                 d[v] = g[u][v];
//         }
//     }
//     return ans;
// }
// int main()
// {
//     cin>>n;
//     for(int i=1; i<=n; i++)
//         for(int j=1; j<=n; j++)
//             cin>>g[i][j];
//     int q;    cin>>q;
//     while(q--){
//         int a,b;    cin>>a>>b;
//         g[a][b] = g[b][a] = 0;
//     }
//     cout<<prim(1);

//     return 0;
// }

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值