HDOJ树形DP专题之Accumulation Degree

题目链接

题目大意:给定一个流量网络,网络的拓扑结构是无根树,定义A(k)以结点k为源点,其他叶子结点为汇点的最大流量,求的是A(k)的最大值(k=1,2,3……n)。

分析:这题跟树形DP专题Computer那题有点像,那题是距离,这题是流量,本质还是一样。从结点k流出的流量,要么经过儿子结点流出,要么经过父亲结点流出。先DP求每个结点经过儿子结点能流出的最大流量是s[k],在DP求每个结点经过父亲结点能流出的最大流量f[k]。最后结果是MAX(s[k]+f[k]),k=1,2,3...n。

s[k]=sum(MIN(s[i],wik)),i是k的儿子结点且不是叶子结点。s[k]=sum(wik),i是k的儿子结点且是叶子结点。

f[k]=MIN(wik,s[i]-MIN(wik,s[k])+f[i]),i是k的父亲结点且不是叶子结点。f[k]=wik,i是k的父亲结点且是叶子结点。

这题还有一个关键是如何保存结点之间的容量,并且可以根据结点快速访问,最开始我是用并查集求结点k到根结点的容量和(距离),最后超时了。后来用d2p[k]来保存结点k到其父亲结点的容量就AC了。

通过这题的训练,让我进一步理解了“用数组可以搞定一切数据结构”这句话。

View Code
 1 #include <stdio.h>
 2 #include <string.h>
 3 #define N 200001
 4 #define MAX(a,b) ((a)>(b)?(a):(b))
 5 #define MIN(a,b) ((a)<(b)?(a):(b))
 6 int u[2*N],v[2*N],w[2*N],next[2*N],first[N];
 7 int firstd[N],nextd[N];
 8 int p[N],d[N],d2p[N],dmax,n;
 9 long long s[N],f[N],ans;
10 char vis[N];
11 void addEdge(int a,int b,int l,int e)
12 {
13   u[e]=a,v[e]=b,w[e]=l;
14   next[e]=first[a];
15   first[a]=e;
16 }
17 void dfs(int a,int fa)
18 {
19   int e,b;
20   d[a]=(fa==-1?0:d[fa]+1);
21   nextd[a]=firstd[d[a]];
22   firstd[d[a]]=a;
23   dmax=MAX(dmax,d[a]);
24   for(e=first[a];e>=0;e=next[e])
25   {
26     b=v[e];
27     if(b!=fa) dfs(b,p[b]=a),vis[a]++,d2p[b]=w[e];
28   }
29 }
30 void dp1()
31 {
32   int i,a,b,tmp;
33   memset(s,0,sizeof(s));
34   for(i=dmax;i>0;i--)
35   {
36     for(b=firstd[i];b>=0;b=nextd[b])
37     {
38       a=p[b];
39       if(vis[b]==0) tmp=d2p[b];
40       else  tmp=MIN(s[b],d2p[b]);
41       s[a]+=tmp;
42     }
43   }
44 }
45 long long dp(int b)
46 {
47   int a=p[b],tmp;
48   if(f[b]!=-1)  return f[b];
49   if(a==-1) return f[b]=0;
50   if(vis[a]==0) return f[b]=d2p[b];
51   if(vis[b]==0) tmp=d2p[b];
52   else  tmp=MIN(s[b],d2p[b]);
53   return f[b]=MIN(s[a]-tmp+dp(a),d2p[b]);
54 }
55 int main()
56 {
57   int t,i,a,b,l;
58   scanf("%d",&t);
59   while(t--)
60   {
61     scanf("%d",&n);
62     memset(first,-1,sizeof(first));
63     memset(next,-1,sizeof(next));
64     for(i=0;i<n-1;i++)
65     {
66       scanf("%d%d%d",&a,&b,&l),a--,b--;
67       addEdge(a,b,l,2*i);
68       addEdge(b,a,l,2*i+1);
69     }
70     p[0]=-1;
71     dmax=0;
72     memset(vis,0,sizeof(vis));
73     vis[0]=-1;
74     memset(firstd,-1,sizeof(firstd));
75     memset(nextd,-1,sizeof(nextd));
76     dfs(0,-1);
77     dp1();
78     memset(f,-1,sizeof(f));
79     for(i=0;i<n;i++)  dp(i);
80     ans=0;
81     for(i=0;i<n;i++)  ans=MAX(ans,s[i]+f[i]);
82     printf("%lld\n",ans);
83   }
84   return 0;
85 }

 

posted @ 2012-05-03 19:06  BeatLJ  阅读(310)  评论(0编辑  收藏  举报