UVA 1395 Slim Span(kruskal算法)

来源:互联网 发布:淘师湾算法与问题解决 编辑:程序博客网 时间:2024/06/05 03:57

题意:题目中要求求出,最苗条的生成树, 最苗条的生成树的定义是权值最大的边减去权值最小的边的权值差最小。

解题思路:

首先对读入的边进行排序,然后枚举最小的权值边。具体就是比当前枚举的边要小的边不会加入生成树。

注意两条边的情况, 和无边的情况。

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4141


Memory: 0 KB Time: 76 MSLanguage: C++11 4.8.2 Result: Accepted

#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<cctype>#include<list>#include<iostream>#include<map>#include<queue>#include<set>#include<stack>#include<vector>using namespace std;#define FOR(i, s, t) for(int i = (s) ; i <= (t) ; ++i)#define REP(i, n) for(int i = 0 ; i < (n) ; ++i)int buf[10];inline long long read(){    long long x=0,f=1;    char ch=getchar();    while(ch<'0'||ch>'9')    {        if(ch=='-')f=-1;        ch=getchar();    }    while(ch>='0'&&ch<='9')    {        x=x*10+ch-'0';        ch=getchar();    }    return x*f;}inline void writenum(int i){    int p = 0;    if(i == 0) p++;    else while(i)        {            buf[p++] = i % 10;            i /= 10;        }    for(int j = p - 1 ; j >= 0 ; --j) putchar('0' + buf[j]);}/**************************************************************/#define MAX_N 110const int INF = 0x3f3f3f3f;int parent[MAX_N];int top = 0;int n;struct node{    int u, v, w;}edge[MAX_N * MAX_N /2];bool cmp(node a, node b){    return a.w < b.w;}int find(int a){    while(a != parent[a])    {        a = parent[a];    }    return a;}void unite(int a, int b){    int fa = find(a);    int fb = find(b);    if(fa == fb) return;    parent[fb] = fa;}bool same(int a,int b){    return find(a) == find(b);}inline void add_edge(int u, int v, int w){    edge[top].u = u;    edge[top].v = v;    edge[top].w = w;    top++;}inline void init(int n){    for(int i = 0 ; i <= n ; i++)    {        parent[i] = i;    }}int kruskal(int cnt){    int all = 1;    int res = -1;    for(int i = cnt ; i < top ; i++)    {        int a = edge[i].u;        int b = edge[i].v;        if(!same(a, b) || n == 2)        {            unite(a, b);            if(edge[i].w > res)            {                res = edge[i].w;            }            all++;        }        if(all >= n - 1) return res;    }    return INF;}int main(){    while(~scanf("%d", &n) && n)    {        init(n);        top = 0;        int m = read();        int u, v, w;        for(int i = 0 ; i < m ; i++)        {            u = read();            v = read();            w = read();            add_edge(u, v, w);        }        sort(edge, edge + top, cmp);        int ans = INF;        for(int i = 0 ; i < top ; i++)        {            unite(edge[i].u, edge[i].v);            int ret = kruskal(i) - edge[i].w;            if(ret < ans && ret >= 0) ans = ret;            init(n);        }        if(ans > 100000) ans = -1;        cout<<ans<<endl;    }    return 0;}


0 0