URAL 1416 Confidentia [次小生成树]

题意:

第一行n m代表n个点m条无向边。

接下来m行每行abc,代表ab之间有一条长度为c的无向边。

求:

最小生成树的边权和  次小生成树的边权和

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#define INF 0x3f3f3f3f
using namespace std;
int pho[505][505],n,total,dis[505],from[505],dp[505][505];
bool vis[505];
void prim(int pos){
    vis[pos]=1;
    for(int i=1;i<=n;i++){
        if(dis[i]>pho[pos][i]){
            dis[i]=pho[pos][i];
            from[i]=pos;
        }
    }
    int mmin=INF,next=-1;
    for(int i=1;i<=n;i++){
        if(vis[i]==0&&mmin>dis[i]){
            mmin=dis[i];
            next=i;
        }
    }
    if(next>0){
        for(int i=1;i<=n;i++){
            if(vis[i]){
                dp[i][next]=max(dp[i][from[next]],mmin);
            }
        }
        pho[from[next]][next]=INF;
        pho[next][from[next]]=INF;
        total+=mmin;
        prim(next);
    }
}
int main()
{
    int m;
    scanf("%d%d",&n,&m);
    memset(pho,0x3f,sizeof(pho));
    memset(dis,0x3f,sizeof(dis));
    for(int i=0;i<m;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        pho[a][b]=c;pho[b][a]=c;
    }
    prim(1);
    printf("Cost: %d
",total);
    bool ok=0;
    int tans=INF;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(pho[i][j]!=INF){
                ok=1;
                tans=min(tans,total-max(dp[i][j],dp[j][i])+pho[i][j]);
            }
        }
    }
    if(ok==0)tans=-1;
    printf("Cost: %d
",tans);
}
原文地址:https://www.cnblogs.com/tun117/p/5420911.html