次小生成树

#include<cstring>
#include<iostream>
#include<cstdio>
#define maxn 105
#define INF 0x3f3f3f3f
using namespace std; 
int head[maxn],maxcost[maxn][maxn],map[maxn][maxn];
bool used[maxn][maxn];//m 
int n,m,t,cnt,x,y,z,vis[maxn],d[maxn],pre[maxn];
int prim(int s)
{
    int res=0;
    memset(maxcost,0,sizeof(maxcost));
    for(int i=1;i<=n;i++)
        vis[i] = 0, d[i] = INF, pre[i]=i;

    d[s]=0;
    for(int i=0;i<n;i++)//循环计数 
    {
        int mn=INF, index=-1;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j] && d[j]<mn)
            {
                mn=d[j];
                index=j;
            }
        }
        if(index==-1)
            break;

        res+=mn;
        vis[index]=1;
        used[index][pre[index]]=used[pre[index]][index]=1;

        for(int j=1;j<=n;j++)
            if(vis[j])//已经访问过的肯定是生成树的一部分 
                maxcost[index][j] = maxcost[j][index] = 
                    max(maxcost[pre[index]][j],d[index]);//pre[index]一定在生成树中    

        for(int j=1;j<=n;j++)//更新全部链接index的点的权值 
        {
            if(!vis[j] && map[index][j]<d[j])
            {
                d[j] = map[index][j];
                pre[j] = index;
            }
        }
    }
    return res;
}
int exprim(int n,int mins)
{
    int ans=INF;
    for(int i=1;i<=n;i++)//枚举最小生成树之外的边
        for(int j=i+1;j<=n;j++)
            if(map[i][j]!=INF && !used[i][j])
            {
                ans=min(ans,mins+map[i][j]-maxcost[i][j]);
            }
    if(ans==INF) return -1;
    return ans;
}
void judge(int n)
{
    int ans=prim(n);
    if (ans == -1)
    {
        puts("Not Unique!");
        return;
    }
    if (exprim(n, ans) == ans)
    printf("Not Unique!
");
    else
    printf("%d
", ans);
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        cnt=0;
        memset(head,0,sizeof head);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                map[i][j]=map[j][i]=INF; 
        memset(used,0,sizeof used);
        for(int i=1;i<=n;i++)
            map[i][i]=0; 
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            map[x][y]=z;
            map[y][x]=z; 
        }
        judge(n);
    }
} 
原文地址:https://www.cnblogs.com/water-radish/p/9280553.html