JOYOI TYVJ1391 走廊潑水節 Kruskal應用

JOYOI TYVJ1391 走廊潑水節 Kruskal應用


題面:

一共有N個OIER打算參加這個潑水節,同時很湊巧的是正好有N個水龍頭。N個水龍頭之間正好有N-1條小道,並且每個水龍頭都可以經過小道到達其他水龍頭(這是一棵樹)。但是OIER們爲了迎接中中的挑戰,決定修建一些個道路,使得每個水龍頭到每個水龍頭之間都有一條直接的道路連接(也就是構成一個完全圖)。但是OIER們很懶,並且記性也不好,他們只會去走那N-1條小道,並且希望所有水龍頭之間修建的道路,都要大於兩個水龍頭之前連接的所有小道(小道當然要是最短的了)。所以神COW們,幫那些OIER們計算一下吧,修建的那些道路總長度最短是多少?


解題過程:

  • 開始時候想着順着已經有的MST走一遍,比如走到 x -> y這條邊時,將所有和x相連的邊長和 length(x,y)取一個max。但這種想法是錯誤的,因爲對於還沒有加入到當前MST的節點來說,它有可能連到另外一個已經加入當前MST但卻不是x的節點,這樣的話,它們之間的距離沒有取max,可能比length(x,y)更小,導致x->y並非MST中的邊,不和題意。
  • 模擬Kruskal算法的過程,設當前部分MST爲s,被最短邊相連的節點集合爲t,s、t之間其他的邊爲|s| * |t|-1條,令其長度爲length(x,y)+1(這樣使x->y爲MST中的邊以滿足題意),累加這個過程中的(|s||t|-1)(length(x,y)+1)

AC代碼:

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#define rep(i,l,p) for(int i=l;i<=p;i++)
#define MP make_pair
typedef long long ll;
typedef pair<int,int> P;
int T;
int n;
int x,y,z;
int fa[6005];
int sum[6005];
//int a[6005][6005];
struct Edge{
    int x,y;
    int z;
    bool operator<(const Edge &b)const{
        return z > b.z;
    }
};
priority_queue<Edge> pq;
void init(){
    rep(i,1,n) fa[i] = i,sum[i] = 1;
}
int get(int x){
    if(fa[x] == x) return fa[x];
    else return fa[x] = get(fa[x]);
}
ll unit(int x,int y){
    x = get(x);
    y = get(y);
    ll res = 0;
    res += (sum[x]*sum[y]-1);
    sum[x] += sum[y];
    sum[y] = 0;
    fa[y] = x;
    return res;
}




int main(){
//  freopen("in.txt","r",stdin);
    cin >> T;
    int x,y,z;
    Edge t;
    while(T--){
        cin >> n;
    //  memset(a,0,sizeof a);
        memset(sum,0,sizeof sum);
        init();

        rep(i,1,n-1){
            cin >> t.x >> t.y >> t.z;
            pq.push(t);
        }
        ll ans = 0;
        while(!pq.empty()){
            Edge now = pq.top();
            //cout << pq.top().z << endl;
            pq.pop();
            int x = get(now.x),y = get(now.y);
            if(x != y) ans += unit(now.x,now.y)*(now.z+1);
            //cout << ans/(now.z+1) << endl;
        }
        //cout << endl;
        cout << ans << endl;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章