HDU 4424 Conquer a New Region(分治 并查集)

探讨了在给定的树形结构中寻找最优根节点的问题,通过树形DP和分治策略,实现对树中边权的优化计算,旨在找到使所有点到该点的容量和最小的点。

【题意】

给定N个点,M条边的树。定义d(u,v)为路径u到v的容量,其值为路径上最小的边权。求一个点作为root,使得其他所有点到该点的容量和最小,即sum(d(root,v))最小。求最小值。

【分析】

比赛时想到树形dp,怎么也表示不出状态。

考虑到d(u,v)的值是路径上最小的边权值,那么整个图中边权最小的边一定是一个关键边。选出边权最小的边,可以把树分成两个子树,答案在左子树或者右子树上。并且左右子树上的边权都大于选出的边权,那么假设答案在左子树,那右子树到答案点的容量和就是右子树的点数*当前这个最小的边权。最终答案再加上左子树的答案。

同理,如果在右子树也如此。进行比较即可。

这样就把问题按照边分治了。

合并的时候比较左右子树分别作为答案的大小进行合并即可。

分治考虑对边权排序,依次合并,维护一些树,使用并查集即可。

【Mark】

从整体考虑,比较有意思的一题。

 1 #include<stdio.h>
 2 #include<math.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 
 6 #define LL long long
 7 #define maxn 200020
 8 
 9 using namespace std;
10 
11 
12 int cnt[maxn];
13 LL sum[maxn];
14 
15 int fat[maxn];
16 
17 struct edge{
18     int u,v;
19     LL val;
20 }seq[maxn];
21 bool cmp(edge p, edge q)
22 {
23     return p.val > q.val;
24 }
25 int n;
26 
27 int find(int u)
28 {
29     if (fat[u]!=u)
30         fat[u] = find(fat[u]);
31     return fat[u];
32 }
33 int main()
34 {
35     while (scanf("%d",&n)==1)
36     {
37         for (int i=1;i<=n;i++)
38         {
39             fat[i] = i;
40             cnt[i] = 1;
41             sum[i] = 0;
42         }
43         for (int i=1;i<n;i++)
44         {
45             scanf("%d%d%I64d",&seq[i].u,&seq[i].v,&seq[i].val);
46         }
47         sort(seq+1,seq+n,cmp);
48 
49         for (int i=1;i<n;i++)
50         {
51             int u = seq[i].u;
52             int v = seq[i].v;
53             LL val = seq[i].val;
54             int fu = find(u);
55             int fv = find(v);
56 
57             LL tmp1 = sum[fu] + val*cnt[fv];
58             LL tmp2 = sum[fv] + val*cnt[fu];
59             if (tmp1 > tmp2){
60                 fat[fv] = fu;
61                 cnt[fu] += cnt[fv];
62                 sum[fu] = tmp1;
63             }else{
64                 fat[fu] = fv;
65                 cnt[fv] += cnt[fu];
66                 sum[fv] = tmp2;
67             }
68 
69         }
70         printf("%I64d\n",sum[find(1)]);
71     }
72     return 0;
73 }
hdu4424

 

转载于:https://www.cnblogs.com/wangsouc/articles/3302556.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值