zoukankan      html  css  js  c++  java
  • 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]&&i!=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 = i+1;j <= n;j++)               //枚举非MST的边,加入生成树形成环,减去该环上权值最大的边 
            {
                if(!used[i][j]&&map[a][b]!=INF)                                                        
                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] = min(map[a][b],val);
            }
            mst_num=prim();
            smst_num=smst();
            if(mst_num == smst_num)printf("Not Unique!
    ");
            else printf("%d
    ",mst_num);
        }
        return 0;
    }
  • 相关阅读:
    Redis 服务端程序实现原理
    Redis 中的客户端
    Redis 中的数据持久化策略(AOF)
    Redis 中的数据持久化策略(RDB)
    Redis 中的数据库
    Redis 的底层数据结构(对象)
    Redis 的底层数据结构(压缩列表)
    Redis 的底层数据结构(整数集合)
    又离职了~
    如何救活被屏蔽的主机,继续开发工作
  • 原文地址:https://www.cnblogs.com/LjwCarrot/p/9775453.html
Copyright © 2011-2022 走看看