[UVA - 1395] Slim Span 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。

题目链接(vjudge):https://vjudge.net/problem/UVA-1395

题目大意:

输入包含多组数据,以0 0作为结束。

每组数据的第一行有两个整数n,m,分别表示点数和边数。

接下来m行,每行三个整数f,t,v,表示第i条边的起点、终点、边权。

你的任务是找出一棵生成树,使得它的最大边权和最小边权的差值最小。输出这个差值。

如果不存在,输出-1.

(样例太多了所以把它折起来)

 

Sample Input
4 5
1 2 3
1 3 5
1 4 6
2 4 6
3 4 7
4 6
1 2 10
1 3 100
1 4 90
2 3 20
2 4 80
3 4 40
2 1
1 2 1
3 0
3 1
1 2 1
3 3
1 2 2
2 3 5
1 3 6
5 10
1 2 110
1 3 120
1 4 130
1 5 120
2 3 110
2 4 120
2 5 130
3 4 120
3 5 110
4 5 120
5 10
1 2 9384
1 3 887
1 4 2778
1 5 6916
2 3 7794
2 4 8336
2 5 5387
3 4 493
3 5 6650
4 5 1422
5 8
1 2 1
2 3 100
3 4 100
4 5 100
1 5 50
2 5 50
3 5 50
4 1 150
0 0
Sample Output
1
20
0
-1
-1
1
0
1686
50
样例数据

 

 

分析:

因为要求最大边权和最小边权的差值,所以自带排序的Kruscal算法显然更方便一些。

才不是因为我不会写Prim

数据范围比较小,可以枚举加入最小生成树的第一条边,然后尝试找最小生成树。

成功找到最小生成树,就用加入树的最后一条边的权值-第一条边的权值更新答案。

最后如果答案没有被更新,说明不存在生成树,输出-1.

 

AC代码:

 

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstring>
 5 
 6 const int INF = 21474836;
 7 inline void read(int &x)
 8 {
 9     char ch = getchar(),c = ch;x = 0;
10     while(ch < '0' || ch > '9') c = ch,ch = getchar();
11     while(ch <= '9' && ch >= '0') x = (x<<1)+(x<<3)+ch-'0',ch = getchar();
12     if(c == '-') x = -x;
13 }
14 
15 int n,m,f,t,v,ans,cnt,fa[110];
16 int mx,mn;
17 
18 struct Edge
19 {
20     int f,t,v;
21 }e[10000];
22 
23 int cmp(Edge a,Edge b)
24 {return a.v < b.v;}
25 
26 void insert(int f,int t,int v)
27 {
28     e[++cnt].f = f,e[cnt].t = t;
29     e[cnt].v = v;
30 }
31 
32 void init()
33 {
34     cnt = 0;
35     mx = -1,mn = INF;
36     for(int i=1;i<=n;++i)
37         fa[i] = i;
38 }
39 
40 inline int Min(int a,int b)
41 {return a<b?a:b;}
42 
43 inline int Max(int a,int b)
44 {return a>b?a:b;}
45 
46 inline int find(int x)
47 {return fa[x]==x?x:fa[x]=find(fa[x]);}
48 
49 bool merge(int a,int b)
50 {
51     a = find(a),b = find(b);
52     if(a != b)
53     {
54         fa[a] = b;
55         return true;
56     }
57     return false;
58 }
59 
60 int main()
61 {
62 //    freopen("1.txt","r",stdin);
63     while(1)
64     {
65         read(n),read(m);
66         if(!n && !m) break;
67         ans = INF;
68         memset(e,0,sizeof(e));
69         for(int i = 1;i <= m;++ i)
70         {
71             read(f),read(t),read(v);
72             insert(f,t,v);
73             insert(t,f,v);
74         } m = cnt;
75         std::sort(e+1,e+1+m,cmp);
76         for(int j,i = 1;i <= m;++ i)
77         {
78             init();
79             for(j = i;j <= m;++ j)
80             {
81                 if(merge(e[j].f,e[j].t))
82                     cnt ++;
83                 if(cnt == n-1) break;
84             }
85             if(cnt == n-1) ans = Min(ans,e[j].v-e[i].v);
86         }
87         if(ans == INF) printf("-1\n");
88         else printf("%d\n",ans);
89     }
90     return 0;
91 }

 

posted @ 2017-10-27 08:03 超时空灰狼菌 阅读(...) 评论(...) 编辑 收藏