固定点群之间的最大距离(最小生成树)

原题: http://codeforces.com/contest/1081/problem/D

题意:

n个点,m条带权边,k个固定点。一条路的长为多条边中的最大权,两个点之间的距离为最短的路长,对于每个固定点,求到另一个固定点的最大距离。

解析:

首先对于按长度排序,然后遍历进行操作

  • 对于这条边的两个点x、y,如果已经连接,那么说明可以找到比当前路线更优的路(已经得出这两个点的距离),所以Continue;
  • 如果没有连接,说明这两个点的距离就是当前边的长度(遍历边时长度递增,之后的边会更长)。
    固定点群之间的最大距离(最小生成树)_第1张图片
    当一条边连接两个分离的部分(假设4的边连接一个长度为2的集合和为3的集合)时,如果左边的集合和右边的集合都存在固定点,那么说明说明对于左边的点,当前的最远固定点在右边,距离为4
#include
using namespace std;

struct node{
    int x,y,v;
    bool operator < (const node &r)const{
        return v<r.v;
    }
}e[100005];

int fa[100005];

int fi(int x){
    return fa[x]==x?x:fa[x]=fi(fa[x]);
}

int ans[100005];
int have[100005];
int main(){
    int n,m,k;scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)fa[i]=i,have[i]=0;
    vector<int>V;V.reserve(k+1);
    for(int i=1,j;i<=k;i++)scanf("%d",&V[i]),j=V[i],have[j]=1;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].v);
    }
    sort(e+1,e+1+m);
    for(int i=1;i<=m;i++){
        int x=e[i].x,y=e[i].y;
        int f1=fi(x),f2=fi(y);
        if(f1==f2)continue;
        fa[f1]=f2;

        if(have[f1]&&have[f2]){
            ans[f2]=e[i].v;
        }
        else{
            have[f2]+=have[f1];
            ans[f2]=max(ans[f2],ans[f1]);//可能把没有固定点的块当作父亲,注意此时的更新
        }
    }
    for(int i=1;i<=k;i++)printf("%d%c",ans[fi(V[i])],(i==k?'\n':' '));
}


你可能感兴趣的:(图论/搜索)