[poj1987]Distance Statistics

本文深入探讨了一种解决树状结构数据问题的算法——树形动态规划与重心分解。通过对树形结构进行预处理,利用重心分解找到树的重心,并通过动态规划计算最优路径,最终解决了在特定条件下寻找最短路径的问题。代码示例详细展示了算法实现过程,包括初始化、递归计算子树大小、寻找重心节点、计算路径长度等关键步骤。

[poj1741]Tree。。。

(不过说好的数据范围呢。。。)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 char s[10];
 9 int n,m,k;
10 const int N=100000;
11 int h[N],to[N],r[N],w[N],ans,tot,num,root,deep[N],d[N],sz[N],f[N],v[N],sum;
12 void ins(int u,int v,int z){
13     to[tot]=v;
14     w[tot]=z;
15     r[tot]=h[u];
16     h[u]=tot++;
17 }
18 
19 void getDeep(int x,int fa){
20     deep[++num]=d[x];
21     for(int i=h[x];i!=-1;i=r[i]){
22         if(!v[to[i]]&&to[i]!=fa){
23             d[to[i]]=d[x]+w[i];
24             getDeep(to[i],x);
25         }
26     }
27 }
28 void getRoot(int x,int fa){
29     sz[x]=1;
30     f[x]=0;
31     for(int i=h[x];i!=-1;i=r[i]){
32         if(!v[to[i]]&&to[i]!=fa){
33             getRoot(to[i],x);
34             sz[x]+=sz[to[i]];
35             f[x]=max(f[x],sz[to[i]]);
36         }
37     }
38     f[x]=max(f[x],sum-sz[x]);
39     if(f[x]<f[root])root=x;
40 }
41 int calc(int x,int val,int t=0){
42     d[x]=val;
43     num=0;
44     getDeep(x,0);
45     sort(deep+1,deep+1+num);
46     for(int l=1,r=num;l<r;){
47         if(deep[l]+deep[r]<=k){t+=r-l;l++;}
48         else r--;
49     }
50     return t;
51 }
52 void work(int x){
53     ans+=calc(x,0);
54     v[x]=1;
55     for(int i=h[x];i!=-1;i=r[i]){
56         if(!v[to[i]]){
57             ans-=calc(to[i],w[i]);
58             root=0;
59             sum=sz[to[i]];
60             getRoot(to[i],0);
61             work(root);
62         }
63     }
64 }
65 
66 int main(){
67     memset(h,-1,sizeof(h));
68     scanf("%d%d",&n,&m);
69     for(int i=1,u,v,z;i<=m;i++)scanf("%d%d%d%s",&u,&v,&z,s),ins(u,v,z),ins(v,u,z);
70     scanf("%d",&k);
71     f[0]=0x3f3f3f3f;
72     sum=n;
73     getRoot(1,0);
74     work(root);
75     printf("%d\n",ans);
76 }
View Code

 

转载于:https://www.cnblogs.com/KingSann/articles/6349664.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值