• 次小生成树


    #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);
        }
    } 
  • 相关阅读:
    bzoj2002: [Hnoi2010]Bounce 弹飞绵羊 [分块][LCT]
    luoguP1886 滑动窗口 [单调队列]
    bzoj1047: [HAOI2007]理想的正方形
    bzoj1012: [JSOI2008]最大数maxnumber [单调队列]
    树与二叉树之二--二叉树的性质与存储
    树与二叉树之一--基本概念与存储结构
    Markdown段首空格
    C++ atan2
    凸包学习笔记
    Codeforces Round #545 (Div. 1) E. Train Car Selection
  • 原文地址:https://www.cnblogs.com/water-radish/p/9280553.html
Copyright © 2020-2023  润新知