UVA-1395 Slim Span

一道简单的图论题(并查集+Kruskal)
求一个图的的生成树,要求最大边减最小边之差最小,输出权值之差,如果没有,输出-1
要求权值差最小,所以首先将边按权值排序,枚举最小边,对于每个最小边从小到大枚举最大边
用并查集判断是否连通,如果可以生成树更新ans

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 #define inf 0x7f7f7f7f
 7 #define rep(i,n) for(int (i)=0;(i)<(n);i++)
 8 #define ABS(x,y) (x-y>0)?(x-y):(y-x)
 9 #define mem(a) memset(a,0,sizeof(a));
10 #define in(a) cin>>a
11 #define out(a) cout<<a
12 const int maxn=110;
13 struct Edge
14 {
15     int u;
16     int v;
17     int w;
18     Edge(int u,int v,int w):u(u),v(v),w(w){}
19 };
20 int n,m; int p[maxn];
21 int cmp(const Edge& a,const Edge& b){
22     return a.w<b.w;
23 }
24 int find(int x){
25     return p[x]==x?x:p[x]=find(p[x]);
26 }
27 int main()
28 {   //freopen("input.txt","r",stdin);
29     while(scanf("%d%d", &n, &m) == 2 && (n || m)){
30         vector<Edge> e; int u,v,w;
31         for(int i=0;i<m;i++){
32             scanf("%d%d%d", &u, &v, &w);
33             e.push_back(Edge(u,v,w));
34         }
35         sort(e.begin(),e.end(),cmp);
36         int ans=inf; int sign=0;
37         for(int L=0;L<e.size();L++){
38             for(int i=0;i<=n;i++) p[i]=i;
39             int cnt=0; int beg=e[L].w;
40             int end=beg;
41             for(int R=L;R<e.size();R++){
42                 int x=find(e[R].u);;int y=find(e[R].v);
43                 if(x!=y){
44                     ++cnt;
45                     p[x]=y;
46                     end=max(end,e[R].w);
47                 }
48                 if(cnt==n-1) break;
49             }
50             if(cnt==n-1){
51                 sign=1;
52                 ans=min(ans,end-beg);
53             }
54         }
55         if(sign==1) printf("%d\n", ans);
56         else printf("-1\n");
57     }
58     return 0;
59 }
时间: 2024-08-09 14:48:46

UVA-1395 Slim Span的相关文章

UVA 1395 - Slim Span(MST)

UVA 1395 - Slim Span 题目链接 题意:给定一些结点和边,要求出最苗条度最小的生成树,苗条度定义为:生成树中最大权的边减去最小权的边的值 思路:类似建最小生成树的算法,多一步枚举起始边即可 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 105; const int INF = 0x3f3f3f3f; int

UVa 1395 - Slim Span(最小生成树变形)

链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4141 题意: 给出一个n(n≤100)结点的图,求苗条度(最大边减最小边的值)尽量小的生成树. 分析: 首先把边按权值从小到大排序.对于一个连续的边集区间[L,R],如果这些边使得n个点全部连通,则一定存在一个苗条度不超过W[R]-W[L]的生成树(其中W[i]表示排序后第i条边的

11.2.2 例题 11-2 UVA 1395 Slim Span (最大值-最小值尽可能小的生成树)

题目大意: 给你n个点(n<=100),然后,让你找到一棵生成树,使得 最大值-最小值的边权尽可能的小的生成树. 解题思路: 还是按照最小生成树的思路,一开始对所有的边按照权值大小,从小到大排序.然后,对于一个区间[L,R],我们每次枚举的时候,如果这个[L,R]使得所有的n个点都联通了,那么定义他们的苗条度为: 最大值-最小值.这个苗条度肯定是<=cost[r]-cost[l].那么,我们就依次枚举这个l,每次都以[l,m]区间内的边建立最小生成树, 如果不能满足n个点的联通,那么就返回-1

UVa 1395 Slim Span (最小生成树)

题意:给定n个结点的图,求最大边的权值减去最小边的权值最小的生成树. 析:这个和最小生成树差不多,从小到大枚举左端点,对于每一个左端点,再枚举右端点,不断更新最小值.挺简单的一个题. #include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int maxn = 100 + 5; const int INF = 0x3f3f3f3f; int p[maxn]

UVa 1395 Slim Span【最小生成树】

题意:给出n个节点的图,求最大边减最小边尽量小的值的生成树 首先将边排序,然后边的区间,判定在该区间内是否n个点连通,如果已经连通了,则构成一颗生成树, 则此时的苗条度是这个区间内最小的(和kruskal一样,如果在已经构成一颗树的基础上,再继续加入边,由于边都是排过序的,再加入的边一定会更大) 再维护一个最小值就好了 自己写的时候,枚举区间没有写对,然后判断1到n个点连通又写了一个for循环 后来看lrj的代码:发现是这样判断1到n是否连通的,每次枚举一个区间的时候,初始化cnt=n,当cnt

UVA 1395 Slim Span (最小生成树,MST,kruscal)

题意:给一个图,找一棵生成树,其满足:最大权-最小权=最小.简单图,不一定连通,权值可能全相同. 思路:点数量不大.根据kruscal每次挑选的是最小权值的边,那么苗条度一定也是最小.但是生成树有多棵,苗条度自然也有多个,穷举下所有生成树,就知道了结果了.根据“只要起始边不同,生成树必定不同”来穷举起始边. 又发现一可能的坑!!我以为LONG_MAX就是int的正最大值,也就是2147483647=2^31-1,在我的机器上也许如此,在OJ上不一定了,用LONG_MAX转int会不同,得注意.

uva 1395 - Slim Span poj 3522 Slim Span(最小生成树算法)

最近学习了一下 最小生成树 算法. 所谓最小生成树算法,就是给出一个连通图g[ maxn ][ maxn  ], 找出这个连通图的边权和最小的生成图(树). 可以实现这个目的的算法,我叫它最小生成树算法.kruskal算法就是我学到的一种实现这种功能的算法. 对于kruskal算法的描述以及简单的证明在刘汝佳第二版上已经说得够明白 本题就是求 最小生成树 里面的 最大边权和最小边权 相差最小的最小生成树. #include<cstdio> #include<cstring> #in

UVA UVA - 1395 Slim Span

点很少,按边权值排序,枚举枚举L和R,检查连通性.一旦连通,那么更新答案. 判断连通用可以O(1),之前我是O(n)判的,之前写的过了,后来写的T了... #include<bits/stdc++.h> using namespace std; const int maxn = 101; const int maxe = maxn*maxn>>1; int n,m; int u[maxe],v[maxe],w[maxe]; int pa[maxn]; inline bool cmp

1395 - Slim Span (最小生成树)

UVA上的题就是让人眼前一亮,不同于那些赤裸裸的生成树水题,该题稍加了变化,不是求最小生成树,而是求最苗条生成树 . 因为生成树有很多,而且每一棵生成树的最大边与最小边只差也是不确定的 .所以只能枚举所有的生成树 . 套用最小生成树模板 ,我们可以枚举生成树的起点位置,然后向后推终点位置,当n个点全部连通时,那么这棵生成树的边集就是[L,R] .因为边事先都排好序了, 那么该树的苗条值就是e[R] - e[L] . 这样从小到大枚举所有的L ,不断更新答案,就可以了 . 忍不住再说一下并查集,这

【UVA】1395-Slim Span

数学实在练不下去了,只能来水几个图论了,真想像D神一样来句:这道题很简单,直接AC就可以了. 大体思路:按照边的权值排序,枚举区间,利用并查集判断是否构成通路. 14042663 1395 Slim Span Accepted C++ 0.265 2014-08-15 02:11:53 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<v