最小生成树POJ3522 Slim Span[kruskal]


Slim Span
Time Limit:5000MS Memory Limit:65536K
Total Submissions:7594 Accepted:4029

Description

Given an undirected weighted graphG, you should find one of spanning trees specified as follows.

The graphGis an ordered pair (V,E), whereVis a set of vertices {v1,v2, …,vn} andEis a set of undirected edges {e1,e2, …,em}. Each edgeeEhas its weightw(e).

A spanning treeTis a tree (a connected subgraph without cycles) which connects all the n vertices withn− 1 edges. The slimness of a spanning treeTis defined as the difference between the largest weight and the smallest weight among then− 1 edges ofT.


Figure 5: A graphGand the weights of the edges

For example, a graphGin Figure 5(a) has four vertices {v1,v2,v3,v4} and five undirected edges {e1,e2,e3,e4,e5}. The weights of the edges arew(e1) = 3,w(e2) = 5,w(e3) = 6,w(e4) = 6,w(e5) = 7 as shown in Figure 5(b).


Figure 6: Examples of the spanning trees ofG

There are several spanning trees forG. Four of them are depicted in Figure 6(a)~(d). The spanning treeTain Figure 6(a) has three edges whose weights are 3, 6 and 7. The largest weight is 7 and the smallest weight is 3 so that the slimness of the treeTais 4. The slimnesses of spanning treesTb,TcandTdshown in Figure 6(b), (c) and (d) are 3, 2 and 1, respectively. You can easily see the slimness of any other spanning tree is greater than or equal to 1, thus the spanning tree Td in Figure 6(d) is one of the slimmest spanning trees whose slimness is 1.

Your job is to write a program that computes the smallest slimness.

Input

The input consists of multiple datasets, followed by a line containing two zeros separated by a space. Each dataset has the following format.

n m
a1 b1 w1
am bm wm

Every input item in a dataset is a non-negative integer. Items in a line are separated by a space. n is the number of the vertices and m the number of the edges. You can assume 2 ≤n≤ 100 and 0 ≤mn(n− 1)/2.akandbk(k= 1, …,m) are positive integers less than or equal ton, which represent the two verticesvakandvbkconnected by thekth edgeek.wkis a positive integer less than or equal to 10000, which indicates the weight ofek. You can assume that the graphG= (V,E) is simple, that is, there are no self-loops (that connect the same vertex) nor parallel edges (that are two or more edges whose both ends are the same two vertices).

Output

For each dataset, if the graph has spanning trees, the smallest slimness among them should be printed. Otherwise, −1 should be printed. An output should not contain extra characters.

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

Source

Japan 2007

copy一下MST的性质:
  • (1)切割性质:(各边边权均不相同)一条边是连接图中某非全集非空集的点集合S和其补集中所有的边的最小边,那么这条边就在最小生成树中。
  • 证明:回忆kruscal算法的过程,这条边是连接这两个集合的最小边,那么在枚举到这条边之前,这两个集合一定没有被合并
  • (2)回路性质:(各边边权均不相同)图若有回路,那么回路中的最长边一定不在最小生成树中
  • 证明:回路中至少一条边不在最少生成树中,假设最长边在最小生成树中,那么一定存在一条更小的边替代它。
  • (3)最小瓶颈生成树:使最大边权值尽量小的生成树
  • 最小生成树就是这么一棵树,因为kruscal算法的过程
  • (4)最小瓶颈路:找u到v的一条路径满足最大边权值尽量小
  • 先求最小生成树,然后u到v的路径在树上是唯一的,答案就是这条路径
  • 如果只求一次,也可以用spfa稍作变形解决

本题求最苗条的生成树

可以发现对于一个最小边的权值,它对应的MST中的最大边的权值一定是最苗条的

枚举求就可以了

//
//  main.cpp
//  poj3522slim
//
//  Created by Candy on 9/14/16.
//  Copyright © 2016 Candy. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=105,INF=1e9;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x;
}
int n,m,ans=INF;
struct edge{
    int u,v,w;
    bool operator<(const edge &rhs)const{return w<rhs.w;}
}e[N*N];
int p[N];
int find(int x){return x==p[x]?x:p[x]=find(p[x]);}
int kruskal(int st){
    int ans=INF,cnt=0;
    for(int i=1;i<=n;i++) p[i]=i;
    for(int i=st;i<=m;i++){
        int u=e[i].u,v=e[i].v;
        int x=find(u),y=find(v);
        if(x!=y){
            ans=e[i].w;
            p[x]=y;
            if(++cnt==n-1) break;
        }
    }
    if(cnt!=n-1) return -1;
    return ans;
}
int main(int argc, const char * argv[]) {
    while(cin>>n>>m){
        if(n==0&&m==0) break;
        ans=INF;
        for(int i=1;i<=m;i++){
            e[i].u=read();e[i].v=read();e[i].w=read();
        }
        sort(e+1,e+1+m);
        for(int st=1;st<=m-n+2;st++){
            int tmp=kruskal(st);
            if(tmp!=-1) ans=min(ans,tmp-e[st].w);
        }
        if(ans!=INF) printf("%d\n",ans);
        else printf("-1\n");
    }
    return 0;
}

优质内容筛选与推荐>>
1、elasticsearch
2、vim中c/c++源码跳转
3、快速幂乘法
4、探索并发编程(七)------分布式环境中并发问题
5、java 数字转换格式化


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn