zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    CentOS7 安装 JIRA 7.2.x 教程:下载、安装、汉化、破解
    安装 GraphicsMagick
    CentOS 7 yum 安装 Nginx
    CentOS 安装 OpenResty
    软件工程技术面试个人指南
    五线谱
    中央C-高低音谱号里的中央C和其它音节
    使用管道copy同一文件至多个目录下
    refusing to merge unrelated histories
    Viewing A Specific Commit_12
  • 原文地址:https://www.cnblogs.com/algorithms/p/2481187.html
Copyright © 2011-2022 走看看