POJ-1679 The Unique MST(次小生成树)

题目传送门:POJ-1679 The Unique MST

题目大意:

题目给了一个无向图,判断该图的最小生成树是否唯一。

分析:

要求出无向图的次小生成树,若次小生成树的权值和最小生成树权值一样,则最小生成树不唯一,否则唯一。

求次小生成树:首先需要求出最小生成树,然后暴力枚举非最小生成树的边,将边加入最小生成树中,

此时会形成一个环,将环中权值最大的边删除(不是新加入的边),得到另一个生成树,枚举完成后,

取所有新生成树中最小的值,若该值和最小生成树值相等,则最小生成树不唯一,否则唯一。

需要数组:

Max[i][j]:i -->j路径中权值最大的边

pre[i]:  i的直接前驱结点

used[i][j]:判断(i,j)这条边是否在最小生成树中

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX=109;
const int INF=0x3f3f3f3f;
int t,n,m,a,b,val;
int mst_num,smst_num;        
int map[MAX][MAX];
int dist[MAX];
int vis[MAX];
int used[MAX][MAX];                                //记录(i,j)是否为最小生成树中的边 
int pre[MAX];                                      //记录i结点的直接前驱 
int Max[MAX][MAX];                                 //记录i-->j路径中权值最大的边 
int prim()
{
    for(int i = 1;i <= n;i++)                      //初始化 
        dist[i] = INF;
    memset(vis,false,sizeof(vis));
    memset(used,false,sizeof(used));
    memset(pre,0,sizeof(pre));
    memset(Max,0,sizeof(MAX));
    dist[1] = 0;
    int ans = 0;
    for(int i = 1;i <= n;i++)
    {
        int min = INF,pos;
        for(int j = 1;j <= n;j++)
        {
            if(!vis[j]&&dist[j] < min)
            {
                min = dist[j];
                pos = j;
            }
        }
        ans += min;
        vis[pos] = true;
        used[pos][pre[pos]] = used[pre[pos]][pos] = true;            //标记新加入最小生成树的边 
        for(int j = 1;j <= n;j++)
        {
            if(vis[j])Max[j][pos] = max(min,Max[pre[pos]][j]);        //更新pos-->到生成树上点的路径最大边权 
            if(!vis[j]&&dist[j] > map[pos][j])
            {
                dist[j] = map[pos][j];
                pre[j] = pos;                                   //更新前驱 
            }
        }
    }
    return ans;
}
int smst()
{
    int Min=INF;
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= n;j++)               //枚举非MST的边,加入生成树形成环,减去该环上权值最大的边 
        {
            if(!used[i][j])                                                        
            Min = min(Min,mst_num + map[i][j] - Max[i][j]);
        }
    return Min;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);    
        for(int i = 1;i <= n;i++)                                        //初始化 
            for(int j = 1;j <= n;j++)
                map[i][j] = INF;
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&val);
            map[a][b] = map[b][a] = val;
        }
        mst_num=prim();
        smst_num=smst();
        if(mst_num == smst_num)printf("Not Unique!\n");
        else printf("%d\n",mst_num);
    }
    return 0;
} 

猜你喜欢

转载自www.cnblogs.com/LjwCarrot/p/9775453.html