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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。