zoukankan      html  css  js  c++  java
  • poj3585 Accumulation Degree 题解报告

    题目传送门

    【题目大意】

    一个树形水系,有$n$个结点,根结点称为源点,叶子结点称为汇点,每条边都有水量限制$C_{x,y}$($x,y$为这条边的两个端点),源点单位时间流出的水量称为整个水系的流量,求以哪一个结点作为源点整个水系的流量最大。

    【思路分析】

    这是一道“不定根”的树形DP问题,这类题目的特点是,给定一个树形结构,需要以每个结点为根进行一系列统计。我们一般通过两次扫描来求解此类问题:

    1.第一次扫描,任选一个点为根,在“有根树”上执行一次树形DP。

    2.第二次扫描,从刚才选出的根出发,对整棵树执行一次DFS,在每次递归前进行自上而下的推导,计算出“换根”之后的解。

    首先,我们任选一个结点$root$,然后树形DP一下,求出$D_{root}$数组($D[i]$表示在以$i$为根的子树中流量的最大值)。然后设$f[x]$表示以x为源点,流向整个水系的最大流量,则显然$f[root]=D[root]$。假设$f[x]$已经求出,考虑其子结点$y$,则$f[y]$包含两部分:

    1.从$y$流向以$y$为根的子树的流量,已经计算出来。

    2.从$y$沿着到父节点$x$的河道,进而流向水系中其他部分的流量。

    由题意可得,从$x$流向$y$的流量为$min(D[y],c[x][y])$,所以从$x$流向除$y$以外其他部分的流量就是二者之差$f[x]-min(D[y],c[x][y])$。于是,把$y$作为源点,先流到$x$,再流向其他部分的流量就是把这个“差”再与$c[x][y]$取较小值后的结果。

    $$if(du[x]>1) o f[y]=D[y]+min(f[x]-min(D[y],c[x][y])-c[x][y])$$

    $$if(du[x]==1) o f[y]=D[y]+c[x][y]$$

    这是一个由上而下的递推方程,我们通过一次DFS即可实现。

    【代码实现】

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<vector>
     4 #include<cstring>
     5 #define rg register
     6 #define go(i,a,b) for(rg int i=a;i<=b;i++)
     7 #define mem(a,b) memset(a,b,sizeof(a))
     8 using namespace std;
     9 const int N=2e5+2;
    10 int T,n,du[N];
    11 struct node{int to,w;};
    12 vector<node> c[N];
    13 bool v[N];
    14 int d[N],f[N];
    15 void clean(){
    16     mem(v,0);mem(du,0);mem(d,0);mem(f,0);
    17     go(i,1,n) c[i].clear();
    18 }
    19 void dp(int x){
    20     v[x]=1;
    21     int size=c[x].size()-1;
    22     go(i,0,size){
    23         int to=c[x][i].to,w=c[x][i].w;
    24         if(v[to]) continue;
    25         dp(to);
    26         if(du[to]==1) d[x]+=w;
    27         else d[x]+=min(d[to],w);
    28     }
    29     return;
    30 }
    31 void dfs(int x){
    32     v[x]=1;
    33     int size=c[x].size()-1;
    34     go(i,0,size){
    35         int to=c[x][i].to,w=c[x][i].w;
    36         if(v[to]) continue;
    37         if(du[x]==1) f[to]=d[to]+w;
    38         else f[to]=d[to]+min(f[x]-min(d[to],w),w);
    39         dfs(to);
    40     }
    41     return;
    42 }
    43 int main(){
    44     scanf("%d",&T);
    45     while(T--){
    46         scanf("%d",&n);clean();
    47         int x,y,z;
    48         go(i,1,n-1){
    49             scanf("%d%d%d",&x,&y,&z);
    50             c[x].push_back((node){y,z});c[y].push_back((node){x,z});
    51             du[x]++;du[y]++;
    52         }
    53         dp(1);
    54         f[1]=d[1];mem(v,0);
    55         dfs(1);
    56         int ans=0;
    57         go(i,1,n) ans=max(ans,f[i]);
    58         printf("%d
    ",ans);
    59     }
    60     return 0;
    61 }
    代码戳这里
  • 相关阅读:
    bzoj 1061 单纯形法,或转化网络流(待补)
    bzoj 1007 计算几何,单调栈
    bzoj 1015 并查集,离线
    bzoj 1013 高斯消元
    java类继承HttpServlet类实现Servlet程序出现405错误:HTTP method POST is not supported by this URL
    算法的特性和算法设计的要求
    Java实现自定义异常类
    怎么查看 MySQL 数据文件在当前电脑的存储位置
    数据结构的分类
    JS实现“全选”和"全不选"功能
  • 原文地址:https://www.cnblogs.com/THWZF/p/11010281.html
Copyright © 2011-2022 走看看