ACM-ICPC 2015 Changchun Preliminary Contest E.Travel(排序+並查集)

鏈接:

        Travel

題意:

        T組樣例,每組樣例給定一個帶邊權的無向圖,有q個詢問,每次詢問給定x,只保留權值<=x的邊的話,輸出有所有奇數個點的連通塊中點對的數量和。

思路:

        根據邊權大小對邊排序,從小到大逐漸加入圖中,遇到詢問時進行查詢。連通塊大小通過並查集維護。

代碼:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
static const int maxn = 100010;
static const int INF = 0x3f3f3f3f;
static const int mod = (int)1e9 + 7;
static const double eps = 1e-6;
static const double pi = acos(-1);

void redirect(){
    #ifdef LOCAL
        freopen("test.txt","r",stdin);
    #endif
}

struct node{
    int x,y,z;
}p[maxn];

bool operator < (const node& a,const node& b){
    return a.z < b.z;
}

struct Query{
    int id,val;
}q[5050];

bool operator < (const Query& a,const Query& b){
    return a.val < b.val;
}

ll ans[5050];
int sz[maxn];
int fa[maxn];
inline int find(int x){
    if(fa[x] == x)return x;
    fa[x] = find(fa[x]);
    return fa[x];
}
inline void combine(int x,int y,ll& sum){
    int fx = find(x),fy = find(y);
    if(fx != fy){
        sum += (sz[fx]+sz[fy]) * (sz[fx]+sz[fy]-1) - sz[fx]*(sz[fx]-1) - sz[fy]*(sz[fy]-1);
        sz[fx] += sz[fy];
        fa[fy] = fx;
    }
}
int main(){
    redirect();
    int T,n,m,qu;
    scanf("%d",&T);
    while(T--){
        fill(sz,sz+maxn,1);
        for(int i = 1;i < maxn;i++)fa[i] = i;
        scanf("%d %d %d",&n,&m,&qu);
        for(int i = 1;i <= m;i++)scanf("%d %d %d",&p[i].x,&p[i].y,&p[i].z);
        sort(p+1,p+1+m);
        for(int i = 1;i <= qu;i++){
            q[i].id = i;
            scanf("%d",&q[i].val);
        }
        sort(q+1,q+1+qu);
        int j = 1;
        ll sum = 0;
        for(int i = 1;i <= qu;i++){
            while(j <= m && p[j].z <= q[i].val)combine(p[j].x,p[j].y,sum),j++;
            ans[q[i].id] = sum;
        }
        for(int i = 1;i <= qu;i++)printf("%lld\n",ans[i]);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章