Avito Cool Challenge 2018:D. Maximum Distance


D. Maximum Distance

題目鏈接https://codeforces.com/contest/1081/problem/D

題意:

給出一個連通圖以及一些特殊點,現在定義cost(u,v)為一條從u到v的路徑上面邊權的最大值,然后定義dis(u,v)為從u到v所有路徑上面cost的最小值。

最后求所有特殊點到其它特殊點的最大距離...

 

題解:
這個題意似乎有點繞...

我們考慮一下最小生成樹,那么點與點之間的距離就為最小生成樹路徑上面邊權的最大值。

我們來證明一下:假設在最小生成樹上面的路徑cost為w1,另外在原圖中還有一條路徑從u到v,其cost為w2,那么必然有w2>w1的。那么我們最后的dis一定是w1。

那么我們現在的目標就是求特殊點到特殊點之間的最大距離。注意一下這里是從一個特殊點到其它所有特殊點的最大距離。

我們知道在Kruskal加邊時,后加的邊權一定時大於前面的邊權的,既然要求最大權值,那么我們可以想加的最后一條邊是否可以作為答案。

我們假設現在有兩個集合,現在將其連接起來,當滿足兩個集合里面都有特殊點時我們就可以更新答案了,否則就不行。

所以我們合並的時候順帶維護一下集合里面特殊點的信息就可以了。

 

代碼如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e5+5;
struct Edge{
    int u,v,w;
    bool operator < (const Edge&A)const{
        return w<A.w;
    }
}e[N];
int n,m,k;
int a[N],f[N],val[N];
int find(int x){
    if(x==f[x]) return f[x];
    f[x]=find(f[x]);
    return f[x];
}
int main(){
    cin>>n>>m>>k;
    int tot=k;
    for(int i=1,t;i<=k;i++){
        cin>>t;
        a[t]=1;
    }
    for(int i=1;i<=m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        e[i]=Edge{u,v,w};
    }
    for(int i=1;i<=n;i++) f[i]=i;
    sort(e+1,e+m+1);
    int ans;
    for(int i=1;i<=m;i++){
        int u=e[i].u,v=e[i].v,w=e[i].w;
        int fx=find(u),fy=find(v);
        if(fx==fy) continue;
        f[fx]=fy;
        if(a[u]) val[fx]++;if(a[v]) val[fy]++;
        if(val[fx]&&val[fy]) ans=w;
        val[fy]+=val[fx];
    }
    for(int i=1;i<=k;i++) cout<<ans<<" ";
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM