码迷,mamicode.com
首页 > 其他好文 > 详细

poj 1679 The Unique MST (次小生成树)

时间:2015-06-02 17:02:07      阅读:82      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:

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

题目大意:

  判断所给的n个节点,m条无向边,构成的无向图是否只存在唯一的最小生成树?

解题思路:

  可以用prim求出最小生成树,再求次小生成树,两者进行比较即可。

  1 #include <cmath>
  2 #include <string>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <iostream>
  6 #include <algorithm>
  7 using namespace std;
  8 const int maxn = 110;
  9 const int INF = 0x3f3f3f3f;
 10 
 11 int cost[maxn][maxn], vis[maxn], lowc[maxn];
 12 int pre[maxn], used[maxn][maxn], Max[maxn][maxn];
 13 //pre[i]为i在MST中的前驱,used记录边的使用情况,Max[i][j]表示在MST中i到j中最长的边
 14 void init ()
 15 {
 16     for (int i=0; i<maxn; i++)
 17         for (int j=0; j<maxn; j++)
 18             if (i == j)
 19                 cost[i][j] = 0;
 20             else
 21                 cost[i][j] = INF;
 22 }
 23 int prim (int n)
 24 {
 25     int i, j, sum = 0;
 26     memset (vis, 0, sizeof(vis));
 27     memset (Max, 0, sizeof(Max));
 28     memset (used, 0, sizeof(used));
 29     vis[1] = 1;
 30 
 31     for (i=1; i<=n; i++)
 32     {
 33         pre[i] = 1;
 34         lowc[i] = cost[1][i];
 35     }
 36 
 37     for (i=1; i<n; i++)
 38     {
 39         int mini = INF;
 40         int p;
 41         for (j=1; j<=n; j++)
 42         {
 43             if (!vis[j] && mini > lowc[j])
 44             {
 45                 p = j;
 46                 mini = lowc[j];
 47             }
 48         }
 49         if (INF == mini)
 50             return -1;
 51         vis[p] = 1;
 52         used[p][pre[p]] = used[pre[p]][p] = 1;
 53         //记录边的使用情况
 54         sum += mini;
 55         for (j=1; j<=n; j++)
 56         {
 57             if (vis[j])
 58                 Max[j][p] = max(Max[j][pre[p]], lowc[p]);
 59             //如果j已经在MST中,则需要更新j到p的最长边
 60             else if (lowc[j] > cost[p][j])
 61             {
 62                 lowc[j] = cost[p][j];
 63                 pre[j] = p;
 64                 //如果加入最小花费优化成功,j就需要改变前驱
 65             }
 66         }
 67     }
 68     return sum;
 69 }
 70 int smst (int n, int ans)
 71 {
 72     int i, j, mini = INF;
 73     for (i=1; i<=n; i++)//枚举所有的边
 74         for (j=i+1; j<=n; j++)
 75         if (cost[i][j] != INF && !used[i][j])//如果当前边没有被使用过,就用当前边代替最大权边
 76             mini = min(mini, ans - cost[i][j] + Max[i][j]);
 77     if (mini == INF)
 78         return -1;
 79     return mini;
 80 }
 81 int main ()
 82 {
 83     int t, n, m;
 84     scanf ("%d", &t);
 85     while (t --)
 86     {
 87         scanf ("%d %d", &n, &m);
 88         init ();
 89         while (m --)
 90         {
 91             int x, y, w;
 92             scanf ("%d %d %d", &x, &y, &w);
 93             cost[x][y] = cost[y][x] = w;
 94         }
 95         int num1, num2;
 96         num1 = prim(n);
 97         if (num1 != -1)
 98             num2 = smst (n, num1);
 99 
100         if (num1 == num2)//最小生成树与次小生成树相同
101             printf ("Not Unique!\n");
102         else
103             printf ("%d\n", num1);
104     }
105     return 0;
106 }

 

poj 1679 The Unique MST (次小生成树)

标签:

原文地址:http://www.cnblogs.com/alihenaixiao/p/4546511.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!