E35 树形DP 积蓄程度
视频链接:https://www.bilibili.com/video/BV1GK4y1L7wc/
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N=200010,INF=0x3f3f3f3f; int h[N],to[N*2],w[N*2],ne[N*2],tot; //邻接表 int d[N]; //d[i]记录从i点向下流出的最大流量 int f[N]; //f[i]记录从i点向外流出的最大流量 int deg[N]; //deg[i]记录点i的度数 void add(int a, int b, int c){ to[++tot]=b,w[tot]=c,ne[tot]=h[a],h[a]=tot; } int dfs_d(int u, int fa){ //从叶点向上递推,获取u点的下流量 for(int i=h[u];i;i=ne[i]){ int v=to[i]; if(v==fa) continue; //避免向上查找 int s=dfs_d(v,u); //返回v点的下流量 d[u]+=min(w[i], s); //累加u点的下流量 } if(deg[u]==1) return INF; //特判叶的情况 return d[u]; //返回u点的下流量 } void dfs_f(int u, int fa){ //从根点向下递推,获取v点的全流量 for(int i=h[u];i;i=ne[i]){ int v=to[i]; if(v==fa) continue; if(deg[u]==1) f[v]=d[v]+w[i]; //特判根的情况 else f[v]=d[v]+min(w[i],f[u]-min(w[i],d[v])); dfs_f(v, u); } } int main(){ int t, n; scanf("%d", &t); while(t--){ scanf("%d", &n); tot = 0; memset(h, 0, sizeof h); memset(d, 0, sizeof d); memset(f, 0, sizeof f); memset(deg, 0, sizeof deg); for(int i=1; i<n; i++){ int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a, b, c), add(b, a, c); deg[a]++, deg[b]++; } dfs_d(1,-1); //向上递推下流量 f[1]=d[1]; //根只有向下的流量 dfs_f(1,-1); //向下递推全流量 int ans=0; for(int i=1;i<=n;i++) ans=max(ans,f[i]); printf("%d\n",ans); } return 0; }
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N=200010,INF=0x3f3f3f3f; int h[N],to[N*2],w[N*2],ne[N*2],tot; //邻接表 int d[N]; //d[u]记录从u点向下流出的最大流量 int up[N]; //up[u]记录从u点向上流出的最大流量 int deg[N]; //deg[i]记录点i的度数 void add(int a, int b, int c){ to[++tot]=b,w[tot]=c,ne[tot]=h[a],h[a]=tot; } int dfs_d(int u, int fa){ //从叶点开始向上递推u点的下流量 for(int i=h[u];i;i=ne[i]){ int v=to[i]; if(v==fa) continue; int s=dfs_d(v,u); //返回v点的下流量 d[u]+=min(w[i], s); //累加u点的下流量 } if(deg[u]==1) return w[h[u]]; //若u是叶 return d[u]; //返回u点的下流量 } void dfs_up(int u, int fa){ //从根点开始向下递推v点的上流量 for(int i=h[u];i;i=ne[i]){ int v=to[i]; if(v==fa) continue; if(deg[u]==1) up[v]=w[i]; else if(deg[v]==1) up[v]=min(w[i],d[u]-w[i]+up[u]); else up[v]=min(d[v],min(d[u]-min(d[v],w[i])+up[u],w[i])); dfs_up(v, u); } } int main(){ int t, n; scanf("%d", &t); while(t--){ scanf("%d", &n); tot = 0; memset(h, 0, sizeof h); memset(d, 0, sizeof d); memset(up, 0, sizeof up); memset(deg, 0, sizeof deg); for(int i=1; i<n; i++){ int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a, b, c), add(b, a, c); deg[a]++, deg[b]++; } dfs_d(1,-1); //向上递推下流量 up[1]=0; //根的上流量为0 dfs_up(1,-1); //向下递推上流量 int ans=0; for(int i=1;i<=n;i++) ans=max(ans,up[i]+d[i]); printf("%d\n",ans); } return 0; }