CDOJ 1636 梦后楼台高锁,酒醒帘幕低垂

给你一个有n个点和m条边的无向连通图,每条边都有一个权值w.
我们定义,对于一条路径,它的Charm value为该路径上所有边的权值的最大值与最小值的差.
询问从1n的所有路径的Charm value的最小值.

Input

第一行有两个整数n,m(1n200,n1m1000),表示该图有nn个点和mm条边.
接下来m行,每行三个整数u,v,w(1u,vn,1w1000000),表示点uu和点vv之间有一条权值为w的边.

Output

输出一个数,即从1n的所有路径的Charm value的最小值.

Sample input and output

Sample InputSample Output
4 4
3 4 1
2 3 2
1 2 4
2 4 3
1

Source

2017 UESTC Training for Graph Theory
思路
首先,我们要找一条从1到n路径,使得路径上权重小的尽量大、权重大的尽量小
这就和Kruskal算法贪心的思想不谋而合
对边的权重按从小到大进行排序,从i=0开始对j>=i的边集构建最小生成树,对每个i求一个Charm value(可能对于某个i不存在Charm value),最后取最小值就OK了
#include <iostream>
#include <cstdlib>
#include <algorithm>
using namespace std;

struct edge{
    int u,v,w;
};
int V,E,id[210];
edge e[1010];

bool cmp(const edge &a,const edge &b) {
    return a.w<b.w;
}

int find(int x) {
    return (x==id[x])?x:(id[x]=find(id[x]));
}

int main() {
    int ru,rv,charmvalue=1000010;
    cin>>V>>E;
    for (int i=0; i<E; i++)
        cin>>e[i].u>>e[i].v>>e[i].w;
    sort(e, e+E, cmp);
    for (int i=0; i<E;i++) {
        for (int k=0; k<=V; k++)
            id[k]=k;
        for (int j=i; j<E; j++) {
            ru=find(e[j].u);
            rv=find(e[j].v);
            if (ru==rv)
                continue;
            id[ru]=rv;
            if (find(1)==find(V)) {
                charmvalue=min(charmvalue,abs(e[i].w-e[j].w));
                break;
            }
        }
    }
    cout<<charmvalue;
}
posted @ 2017-11-25 16:16  soildom  阅读(302)  评论(0编辑  收藏  举报