集合问题 离线+并查集 HDU 3938

题目大意:给你n个点,m条边,q个询问,每条边有一个val,每次询问也询问一个val,定义:这样条件的两个点(u,v),使得u->v的的价值就是所有的通路中的的最长的边最短。问满足这样的点对有几个。

思路:我们先将询问和边全部都按照val排序,然后我们知道,并查集是可以用来划分集合的,所以我们就用并查集来维护每一个集合就行了。

 

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
const int maxn = 1e5 + 5;
const int maxm = 5e5 + 5;
int n, m, Q;
pair<int, pair<int, int> > p[maxm];///
pair<int, int> q[maxn];///询问
int par[maxn];
LL sum[maxn], ans[maxn];

int pfind(int x){
    if (x == par[x]) return x;
    return par[x] = pfind(par[x]);
}

int main(){
    while (scanf("%d%d%d", &n, &m, &Q) == 3){
        for (int i = 1; i <= m; i++){
            int u, v, val;
            scanf("%d%d%d", &u, &v, &val);
            p[i] = mk(val, mk(u, v));
        }
        sort(p + 1, p + 1 + m);
        memset(sum, 0, sizeof(sum));
        for (int i = 1; i <= n; i++) par[i] = i, sum[i] = 1;
        for (int i = 1; i <= Q; i++){
            int val; scanf("%d", &val);
            q[i] = mk(val, i);
        }
        sort(q + 1, q + 1 + Q);
        int j = 1; LL cnt = 0;
        for (int i = 1; i <= m && j <= Q; ){
            while (i <= m && p[i].first <= q[j].first){
                int pa = pfind(p[i].second.first);
                int pb = pfind(p[i].second.second);
                i++;
                if (pa == pb) continue;
                cnt += sum[pa] * sum[pb];
                ///printf("sum[%d] = %I64d sum[%d] = %I64d\n", pa, sum[pa], pb, sum[pb]);
                par[pa] = pb;
                sum[pb] += sum[pa];
            }
            while (j <= Q && q[j].first < p[i].first){
                ans[q[j].second] = cnt;
                j++;
            }
        }
        while (j <= Q){
            ans[q[j].second] = cnt;
            j++;
        }
        for (int i = 1; i <= Q; i++){
            printf("%I64d\n", ans[i]);
        }
    }
    return 0;
}
View Code

 

posted @ 2016-09-14 20:25  知る奇迹に  阅读(158)  评论(0编辑  收藏  举报