UVA 1664 - Conquer a New Region(并查集)
2015-08-24 21:13
274 查看
该题巧妙的运用了并查集,运用了类似于最小生成树算法的过程 ,通过该题可以对并查集有一个更深的理解 。
由于i和j唯一通路上容量的最小值为该两点的容量,求一个点到其他所有点的容量最大值 。
首先,解决两点的容量问题 ,我们将所有边从大到小排序,然后从大到小枚举,我们假设根结点就是要找的城市中心点,那么当又加入一条边时,该边的两个顶点所在的集合设为A、B,集合A、B的顶点a、b,要让谁当中心点呢? 易知:无论谁当中心点,它与另一个集合中任一点的容量都为该边长度(因为是从大到小枚举的)。
那么为了求出总容量,我们要维护一些值,用空间换时间 。 维护每个顶点的总容量sum[i],维护每个顶点与之相连的顶点数量,cnt[i],当前答案ans 。
那么对于a、b点,如果以a为中心,总容量为sum[a] + cnt[b] * e[i].c 。 反之亦然,哪个量大,则以哪个点为城市中心,也就是并查集的根结点 。
该题的巧妙之处在于,将答案结点维护成并查集的根结点,快速的找出一个集合中的城市中心 。
并查集用了路径压缩之后其实已经很快了,没有必要在改变树的高度,因为那样会改变根结点,不仅写起来麻烦,还丢掉了许多很好的特性 。
该题就是通过这些特性,维护一些重要的量以达到快速求解的目的 。 请读者细细品味 。
细节参见代码:
由于i和j唯一通路上容量的最小值为该两点的容量,求一个点到其他所有点的容量最大值 。
首先,解决两点的容量问题 ,我们将所有边从大到小排序,然后从大到小枚举,我们假设根结点就是要找的城市中心点,那么当又加入一条边时,该边的两个顶点所在的集合设为A、B,集合A、B的顶点a、b,要让谁当中心点呢? 易知:无论谁当中心点,它与另一个集合中任一点的容量都为该边长度(因为是从大到小枚举的)。
那么为了求出总容量,我们要维护一些值,用空间换时间 。 维护每个顶点的总容量sum[i],维护每个顶点与之相连的顶点数量,cnt[i],当前答案ans 。
那么对于a、b点,如果以a为中心,总容量为sum[a] + cnt[b] * e[i].c 。 反之亦然,哪个量大,则以哪个点为城市中心,也就是并查集的根结点 。
该题的巧妙之处在于,将答案结点维护成并查集的根结点,快速的找出一个集合中的城市中心 。
并查集用了路径压缩之后其实已经很快了,没有必要在改变树的高度,因为那样会改变根结点,不仅写起来麻烦,还丢掉了许多很好的特性 。
该题就是通过这些特性,维护一些重要的量以达到快速求解的目的 。 请读者细细品味 。
细节参见代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 200000 + 5; int n,m,p[maxn]; ll sum[maxn],cnt[maxn]; struct Edge{ ll a,b,c; bool operator < (const Edge& rhs) const { return c > rhs.c; } }e[maxn]; int findd(int x) { return p[x] == x ? x : p[x] = findd(p[x]); } ll solve() { for(int i=1;i<=n;i++) { p[i] = i ; sum[i] = 0 ; cnt[i] = 1; } ll ans = 0; sort(e,e+n-1); for(int i=0;i<n-1;i++) { int x = findd(e[i].a) , y = findd(e[i].b); ll suma = sum[x]+cnt[y]*e[i].c,sumb = sum[y]+cnt[x]*e[i].c; if(suma < sumb) { p[x] = y; sum[y] = sumb; cnt[y] += cnt[x]; ans = sum[y]; } else { p[y] = x; sum[x] = suma; cnt[x] += cnt[y]; ans = sum[x]; } } return ans; } int main() { while(~scanf("%d",&n)) { for(int i=0;i<n-1;i++) scanf("%lld%lld%lld",&e[i].a,&e[i].b,&e[i].c); printf("%lld\n",solve()); } return 0; }
相关文章推荐
- UVAoj 1342 - That Nice Euler Circuit
- Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call
- 08-排序3. Talent and Virtue (25)
- UITextField 弹出键盘的外观(类型)设置
- UIScorllView和UIPageController的区别和实现图片轮播
- UIImageView动画 、自定义View 和手势的简单实用 Tom 猫 全部功能实现
- Android API Guides 安卓API指导----第一部分:Introduction(介绍)
- IOS UITextField 跳转到搜索界面
- Android UI之自定义AutoCompleteTextView
- StringBuffer和StringBuilder
- Android UI之自定义SeekBar
- UI -响应者链
- Easyui-Datagrid—表头灵活显示
- Design Pattern_Java:Builder Pattern
- UIView常用的方法
- Android UI设计:ListView适配器——ArrayAdapter、SimpleAdapter与BaseAdapter
- Go web之旅(Request分析)
- UIKeyboard
- Android UI设计——RadioButton和CheckBox控件
- STL Algorithms 之 unique