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

生成树专题

时间:2015-07-30 09:22:21      阅读:97      评论:0      收藏:0      [点我收藏+]

标签:

uvalive3887

给定一个带权的无向图,求得一棵最小生成树,是的树中的最大边权-最小边权的差值最小

分析:当确定一个最小边时(其他的边的权值都比他大),那么之后按照kruskal算法得到的最小生成树,

此时得到的最小生成树的最大权值也肯定是最小的,因为是kruskal是按照贪心来选边的。

所以只要不断的枚举是哪条边作为最小边,然后生成最小生成树,记录所有差值中最小的一个就是答案。

时间复杂度是O(m*m*logm)

技术分享
  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <algorithm>
  5 #include <iostream>
  6 #include <queue>
  7 #include <stack>
  8 #include <vector>
  9 #include <map>
 10 #include <set>
 11 #include <string>
 12 #include <math.h>
 13 using namespace std;
 14 #pragma warning(disable:4996)
 15 #pragma comment(linker, "/STACK:1024000000,1024000000")
 16 typedef long long LL;                   
 17 const int INF = 1<<30;
 18 /*
 19 最大边的权值减去最小边的权值      要最小的生成树, 
 20 即树的边权尽可能相近
 21 
 22 枚举最小边的权值,然后生成生成树 , 然后计算权值之差,  取取最小的那一个
 23 时间复杂度是m * m * logm  ,
 24 
 25 
 26 因为生成树是
 27 */
 28 const int N = 350 + 10;
 29 struct Edge
 30 {
 31     int u, v, dis;
 32     bool operator<(const Edge&rhs)
 33     {
 34         return dis < rhs.dis;
 35     }
 36 }g[N*N];
 37 int fa[N];
 38 int find(int x)
 39 {
 40     if (x == fa[x])
 41         return x;
 42     return fa[x] = find(fa[x]);
 43 }
 44 int kruskal(int n, int j ,int m)
 45 {
 46     for (int i = 0; i <= n; ++i)
 47     {
 48         fa[i] = i;
 49     }
 50     int cnt = 0, ret = 0;
 51     for (int i = j; i < m; ++i)
 52     {
 53         int fx = find(g[i].u);
 54         int fy = find(g[i].v);
 55         if (fx != fy)
 56         {
 57             fa[fx] = fy;
 58             if (cnt == 0)
 59                 ret = g[i].dis;
 60             if (cnt != 0 && g[i].dis - ret > ans)
 61                 return -1;
 62             cnt++;
 63             if (cnt == n - 1)
 64                 ret = g[i].dis - ret;
 65         }
 66     }
 67     if (cnt == n - 1)
 68         return ret;
 69     return  -1;
 70 }
 71 
 72 
 73 int main()
 74 {
 75     //freopen("d:/in.txt", "r", stdin);
 76     int n, m;
 77     while (scanf("%d",&n),n)
 78     {
 79         scanf("%d", &m);
 80         for (int i = 0; i < m; ++i)
 81             scanf("%d%d%d", &g[i].u, &g[i].v, &g[i].dis);
 82         sort(g, g + m);
 83         int ans = kruskal(n, 0 ,m);
 84         if (ans == -1)
 85             puts("-1");
 86         else
 87         {
 88             for (int i = 1; i < m; ++i)
 89             {
 90                 int ret = kruskal(n, i, m);
 91                 if (m - i < n - 1)
 92                     break;
 93                 if (ret != -1)
 94                     ans = min(ans, ret);
 95             }
 96             printf("%d\n", ans);
 97         }
 98     }
 99     return 0;
100 }
View Code

 

生成树专题

标签:

原文地址:http://www.cnblogs.com/justPassBy/p/4688135.html

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