HDU 5441 2015长春站online1005(并查集)

这场比赛其实打的还是比较傻逼的,赛后做总结,感觉麟哥和真珍姐讲的还是蛮有道理的,现在如果再做专题的话没有什么意义了,这段时间准备多做点套题。

比赛的时候并不是我写的这题,赛后补了一下,写离线并查集的话,不断插满足条件的边,如果是u,v在两棵不同子树的话,那么这次查找的答案就是ans += 2*cnt[findset(u)]*cnt[findset(v)];这里应该比较好理解。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define LL long long
#define FOR(i,x,y)  for(int i = x;i < y;i ++)
#define IFOR(i,x,y) for(int i = x;i > y;i --)
#define N 20020
#define M 100010
#define Q 5005

using namespace std;

int n,m,q;

int fa[N];

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

struct Edge{
    int u,v;
    int val;
    bool operator < (const Edge& rhs) const{
        return val < rhs.val;
    }
}edge[M];

struct Commend{
    int x;
    int id;
    bool operator < (const Commend& rhs) const{
        return x < rhs.x;
    }
}cmd[Q];

int ans[Q];
int cnt[N];

int main()
{
    //freopen("test.in","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&n,&m,&q);
        FOR(i,0,m){
            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].val);
        }
        sort(edge,edge+m);
        FOR(i,0,q){
            scanf("%d",&cmd[i].x);
            cmd[i].id = i;
        }
        sort(cmd,cmd+q);
        FOR(i,1,n+1)    {fa[i] = i;cnt[i] = 1;}
        int op = 0;
        int tem = 0;
        FOR(i,0,q){
            while(op < m && edge[op].val <= cmd[i].x){
                int u = findset(edge[op].u),v = findset(edge[op].v);
                op++;
                if(u == v)  continue;
                tem += 2*cnt[u]*cnt[v];
                fa[v] = u;
                cnt[u] += cnt[v];
            }
            ans[cmd[i].id] = tem;
        }
        FOR(i,0,q){
            printf("%d\n",ans[i]);
        }
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2015-09-14 12:57  hqwhqwhq  阅读(131)  评论(0编辑  收藏  举报