zoukankan      html  css  js  c++  java
  • POJ-1679 The Unique MST(次小生成树、判断最小生成树是否唯一)

    http://poj.org/problem?id=1679

    Description

    Given a connected undirected graph, tell if its minimum spanning tree is unique. 

    Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the following properties: 
    1. V' = V. 
    2. T is connected and acyclic. 

    Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E') of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E'. 

    Input

    The first line contains a single integer t (1 <= t <= 20), the number of test cases. Each case represents a graph. It begins with a line containing two integers n and m (1 <= n <= 100), the number of nodes and edges. Each of the following m lines contains a triple (xi, yi, wi), indicating that xi and yi are connected by an edge with weight = wi. For any two nodes, there is at most one edge connecting them.

    Output

    For each input, if the MST is unique, print the total cost of it, or otherwise print the string 'Not Unique!'.

    Sample Input

    2
    3 3
    1 2 1
    2 3 2
    3 1 3
    4 4
    1 2 2
    2 3 2
    3 4 2
    4 1 2

    Sample Output

    3
    Not Unique!

    题意:

    给n点m边无重边,求最小生成树是否唯一,如果这棵最小生成树是唯一的那么就输出最小生成树上权的和,不是唯一的就输出Not Unique!

    思路:

    求次小生成树,如果和最小生成树结果一样则不唯一。

    次小生成树:

    次小生成树由最小生成树变化而来,通过最小生成树概念可以知道“次小”只需要通过变化最小生成树上的一条边实现,并且要使得这种变化是最小。

    给出一篇写的挺好的博客:https://blog.csdn.net/qq_27437781/article/details/70821413


    from:https://blog.csdn.net/u011721440/article/details/38735547

    判断最小生成树是否唯一:

    1、对图中每条边,扫描其它边,如果存在相同权值的边,则标记该边。

    2、用kruskal或prim求出MST。

    3、如果MST中无标记的边,则MST唯一;否则,在MST中依次去掉标记的边,再求MST,若求得MST权值和原来的MST权值相同,则MST不唯一。


    from:https://blog.csdn.net/blue_skyrim/article/details/51338375

    次小生成树的求法是枚举最小生成树的每条边,把其中一条边去掉,找到这两点上其他的边,剩下的边形成最小生成树


    kuangbin大佬的博客:https://www.cnblogs.com/kuangbin/p/3147329.html

    思路:

    求最小生成树时,用数组maxval[i][j]来表示MST中i到j最大边权,求完后,直接枚举所有不在MST中的边,替换掉最大边权的边,更新答案 ,注意点的编号从0开始

    原理:

    最小生成树上的不相邻的两点相连必定成成为一个环,所以我们可以尝试枚举这些不相邻的点使他们相连,再删除环中属于最小生成树的最大边(令当前被确定的点为u,已经被确定的点为v,则u--v路径中最大的边要么来自v--pre[u]路径中的最大,要么就是当前被确定的边lowval[u],dp的思想),这样既保证树的结构又能使树的变化最小。这些枚举中最小的结果即为次小生成树。

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <iostream>
      4 #include <string>
      5 #include <math.h>
      6 #include <algorithm>
      7 #include <vector>
      8 #include <stack>
      9 #include <queue>
     10 #include <set>
     11 #include <map>
     12 #include <sstream>
     13 const int INF=0x3f3f3f3f;
     14 typedef long long LL;
     15 const int mod=1e9+7;
     16 //const double PI=acos(-1);
     17 #define Bug cout<<"---------------------"<<endl
     18 const int maxn=110;
     19 using namespace std;
     20 
     21 int G[maxn][maxn];//邻接矩阵 
     22 int vis[maxn];//判断点有没在最小生成树中 
     23 int pre[maxn];//每个点的双亲 
     24 int lowval[maxn];//辅助数组 
     25 int maxval[maxn][maxn];//maxval[i][j]表示在最小生成树中从i到j的路径中的最大边权
     26 int used[maxn][maxn];//判断这条边是否在最小生成树中使用过 
     27 int MST;//最小生成树权值和 
     28 
     29 int Prim(int n,int st)//n为顶点的个数,st为最小生成树的开始顶点
     30 {
     31     fill(lowval,lowval+n,INF);
     32     memset(maxval,0,sizeof(maxval));
     33     memset(pre,-1,sizeof(pre));
     34     memset(used,0,sizeof(used));
     35     memset(vis,0,sizeof(vis));
     36     int ans=0;
     37     lowval[st]=0;
     38     vis[st]=1;
     39     for(int i=0;i<n;i++)
     40     {
     41         if(i!=st&&G[st][i]!=INF)
     42         {
     43             lowval[i]=min(lowval[i],G[st][i]);
     44             pre[i]=st;
     45         }
     46     }
     47     for(int k=0;k<n-1;k++)
     48     {
     49         int MIN=INF;
     50         int t=-1;
     51         for(int i=0;i<n;i++)
     52         {
     53             if(vis[i]==0&&lowval[i]<MIN)
     54             {
     55                 MIN=lowval[i];
     56                 t=i;
     57             }
     58         }
     59 //        if(MIN==INF)    return -1;
     60         ans+=MIN;
     61         vis[t]=1;
     62         used[t][pre[t]]=used[pre[t]][t]=1;//标记这条边在最小生成树中 
     63         for(int i=0;i<n;i++)
     64         {
     65             if(vis[i]) 
     66                 maxval[t][i]=maxval[i][t]=max(maxval[i][pre[t]],lowval[t]);
     67             if(i!=t&&!vis[i]&&G[t][i]<lowval[i])
     68             {
     69                 pre[i]=t;
     70                 lowval[i]=G[t][i];
     71             }
     72         }
     73     }
     74     return ans;
     75 }
     76 
     77 int Judge(int n)
     78 {
     79     int MIN=INF;
     80     for(int i=0;i<n;i++)
     81     {
     82         for(int j=i+1;j<n;j++)
     83         {
     84             if(G[i][j]!=INF && !used[i][j])//边不在最小生成树中 
     85                 MIN=min(MIN,MST-maxval[i][j]+G[i][j]);
     86         }
     87     }
     88     return MIN;
     89 }
     90 
     91 int main()
     92 {
     93     int T;
     94     scanf("%d",&T);
     95     while(T--)
     96     {
     97         int n,m;
     98         scanf("%d %d",&n,&m);
     99         memset(G,INF,sizeof(G));
    100         for(int i=0;i<m;i++)
    101         {
    102             int u,v,w;
    103             scanf("%d %d %d",&u,&v,&w);
    104             u--;v--;//使标号从0开始 
    105             G[u][v]=w;
    106             G[v][u]=w;
    107         }
    108         MST=Prim(n,0);
    109         if(MST==Judge(n))//最小生成树和次小生成树总权值相等 
    110             printf("Not Unique!
    ");
    111         else
    112             printf("%d
    ",MST);
    113     }
    114     return 0;
    115 }
  • 相关阅读:
    更多的bash命令
    简单的Writer和Reader
    矩阵的基本知识
    在Java中如何实现“Pless presss any key to continue.”
    递归思想解决输出目录下的全部文件
    初学File类
    如何避免遭受HTTS中间人攻击
    中间人攻击破解HTTPS传输内容
    LINE最新版6.5.0在iOS上的删除信息取证
    JB for iOS 9.3
  • 原文地址:https://www.cnblogs.com/jiamian/p/11735971.html
Copyright © 2011-2022 走看看