HDU-4424 Conquer a New Region(并查集)

来源:互联网 发布:网络大电影营销方案 编辑:程序博客网 时间:2024/05/19 06:18

题意:

给定n个点的树形图,一个点u到一个点v的路径中边的容量最小的一条边称为S(u, v),让你寻找一个点造成它到其它n-1个点的S(..)加和最大,输出最大加和。

思路:

由于边权较小的边会限制边权较大的边,所以我们先处理边权较大的边,初始时把n个点作为n个集合,然后利用并查集不断合并两个不连通的点集。由于我们之前用较大边权的边形成集合,所以我们对于当前边的两点,去合并它们分别所在的集合,由于它是到此刻最小的边权,所以把一个集合合并至另一个集合就是一个集合的点个数*当前边权w再加入到另一个集合的总权和中。所以进行比较一下然后确定哪个集合加入哪个集合会造成更优从而确定新的集合,这样肯定是正确的,因为之后小的边要加入这个集合中,必定不会使此时的结果更优了。

代码:

#include <bits/stdc++.h>#define ll long longusing namespace std;const int maxn = 2e5+5;struct node{int u, v, w;bool operator<(const node k)const{return w < k.w;}};ll ans[maxn];int num[maxn], f[maxn];int n;priority_queue<node> q;int getF(int x){if(x == f[x]) return x;f[x] = getF(f[x]);return f[x];}int main(){while(~scanf("%d", &n)){for(int i = 1; i <= n; ++i)f[i] = i, num[i] = 1, ans[i] = 0;for(int i = 1; i < n; ++i){int u, v, w;scanf("%d %d %d", &u, &v, &w);q.push((node){u, v, w});}while(!q.empty()){node top = q.top(); q.pop();int u = top.u, v = top.v, w = top.w;int fu = getF(u), fv = getF(v);if(ans[fu]+1ll*num[fv]*w > ans[fv]+1ll*num[fu]*w){ans[fu] += 1ll*num[fv]*w;num[fu] += num[fv];f[fv] = fu;}else{ans[fv] += 1ll*num[fu]*w;num[fv] += num[fu];f[fu] = fv;}}printf("%lld\n", ans[getF(1)]);}return 0ll;}


继续加油~