poj 1679 The Unique MST

次小生成树学习:

顾名思义,次小生成树,就是将图的所有生成树排序后,权值第二小的生成树。

次小生成树的朴素求法是很好想的,即首先求出最小生成树,之后枚举最小生成树中的所有边,将当前枚举的边“禁止使用”,在这基础之上再求最小生成树,将所有边枚举之后的结果取最小值,那就是次小生成树。这个算法简单暴力,但是可想而知的复杂度是比较大的,在图是稠密图的时候,复杂度接近O(n^3)。在规模较大的时候不建议使用。

另一个推荐的求法:在添加最小生成树的边之外的边时,会形成环,这个时候,把在这个环中,且在最小生成树中的边给去掉,这时候就形成了另一个生成树。如何实现这个算法的呢?实际上,对于两个点u,v,我们遍历最小生成树,找出u到v的边中的最大权值的边,用一个数组maxn[u][v]保存起来。当我们往最小生成树中加边时,就直接用w - max[u][v] + 当前添加边的权值,这个式子计算出此时生成树的权值之和。那么maxn[u][v]这个数组是如何求得呢?嗯,bfs,即广度优先搜索,对每一个点都遍历一次生成树,每次更新的值都是当前点到其他点的权值。之后就枚举不在生成树的边进行计算,把每次的结果都保存下来,取最小的,就是次小生成树啦。(或许第k小生成树可以这么求?)这个算法的复杂度为O(n^2)。

例题:

https://vjudge.net/problem/POJ-1679

题意:

这题问的是最小生成树是否唯一。

思路:

那么很显然的,如果说最小生成树不唯一的话,那么最小生成树与次小生成树的权值肯定相等,因为对于在最小生成树中的边来说,至少存在一条不在其中的边,与在其中的边的权值相等,这样才满足不唯一,所以只需要求出次小生成树,判断其与最小生成树是否相等就可以了。

PS:通过这题还学会了用邻接链表表示图,用vector很方便的,就是把以每个点为起点的边搞到一起就ok。

 

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <queue>
  6 using namespace std;
  7 
  8 struct node
  9 {
 10     int x,y,w;
 11 } e[6000];
 12 
 13 struct ord
 14 {
 15     int p,dis;
 16 };
 17 
 18 vector<node> v[105];
 19 
 20 int par[105];
 21 int maxn[105][105];
 22 
 23 bool used[6000],vis[6000];
 24 
 25 void init(int n)
 26 {
 27     for (int i = 1;i <= n;i++)
 28         par[i] = i;
 29 }
 30 
 31 int fin(int x)
 32 {
 33     if (x == par[x]) return x;
 34     else return par[x] = fin(par[x]);
 35 }
 36 
 37 void unit(int x,int y)
 38 {
 39     x = fin(x);
 40     y = fin(y);
 41 
 42     if (x != y) par[x] = y;
 43 }
 44 
 45 bool cmp(node aa,node bb)
 46 {
 47     return aa.w < bb.w;
 48 }
 49 
 50 void adde(int x,int y,int dis)
 51 {
 52     node t;
 53     t.x = x;
 54     t.y = y;
 55     t.w = dis;
 56     v[x].push_back(t);
 57 }
 58 
 59 void bfs(int k)
 60 {
 61     memset(used,0,sizeof(used));
 62 
 63     ord now,nex;
 64 
 65     now.p = k;now.dis = 0;
 66     used[k] = true;
 67 
 68     queue<ord> qq;
 69 
 70     while (!qq.empty()) qq.pop();
 71 
 72     qq.push(now);
 73 
 74     while (!qq.empty())
 75     {
 76         //printf("dsfsd\n");
 77         ord t = qq.front();qq.pop();
 78 
 79         int x = t.p,tmaxn = t.dis;
 80 
 81         for (int i = 0;i < v[x].size();i++)
 82         {
 83             node tt = v[x][i];
 84 
 85             nex.dis = tt.w;nex.p = tt.y;
 86 
 87             if (!used[nex.p])
 88             {
 89                 if (tmaxn > nex.dis) nex.dis = tmaxn;
 90                 used[nex.p] = true;
 91                 maxn[k][nex.p] = nex.dis;
 92                 qq.push(nex);
 93             }
 94         }
 95     }
 96 }
 97 
 98 int main()
 99 {
100     int t;
101 
102     scanf("%d",&t);
103 
104     while (t--)
105     {
106         int n,m;
107 
108         scanf("%d%d",&n,&m);
109 
110         init(n);
111 
112         memset(v,0,sizeof(v));
113         memset(vis,0,sizeof(vis));
114         memset(used,0,sizeof(used));
115 
116         for (int i = 0;i < m;i++)
117         {
118             scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
119         }
120 
121         sort(e,e+m,cmp);
122 
123         int ans = 0;
124 
125         for (int i = 0;i < m;i++)
126         {
127             int x = e[i].x,y = e[i].y;
128 
129             if (fin(x) == fin(y)) continue;
130 
131             unit(x,y);
132 
133             vis[i] = true;
134 
135             ans += e[i].w;
136 
137             adde(x,y,e[i].w);
138             adde(y,x,e[i].w);
139         }
140 
141         for (int i = 1;i <= n;i++)
142         {
143             bfs(i);
144         }
145 
146         int minn = 100000000;
147 
148         for (int i = 0;i < m;i++)
149         {
150             if (!vis[i])
151             {
152                 int tans = ans;
153                 int x = e[i].x,y = e[i].y;
154 
155                 tans -= maxn[x][y];
156 
157                 tans += e[i].w;
158 
159                 if (tans < minn) minn = tans;
160             }
161 
162 
163         }
164 
165         if (minn == ans) printf("Not Unique!\n");
166         else printf("%d\n",ans);
167     }
168 
169     return 0;
170 }

 

posted @ 2017-07-14 21:35  qrfkickit  阅读(171)  评论(0编辑  收藏  举报