2018.10.14 NOIP訓練 水流成河(換根dp)
阿新 • • 發佈:2018-12-15
傳送門 換根dp入門題。
貌似李煜東的書上講過? 不記得了。 先推出以1為根時的答案。 然後考慮向兒子轉移。 我們記表示原樹中以為根的子樹的答案。 表示把根換成時整棵樹的答案。 於是有 注意邊界之後就能過了。 程式碼:
#include<bits/stdc++.h>
#define N 400005
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int n,first[N],cnt,f[N],g[N],ans=0;
struct edge{int v,c,next;}e[N<<1];
inline void add(int u,int v,int c){e[++cnt].v=v,e[cnt].c=c,e[cnt].next=first[u],first[u]=cnt;}
void dfs1(int p,int fa){
bool flag=false;
f[p]=0;
for(int i=first[p];i;i=e[i].next){
int v=e[i].v;
if(v==fa)continue;
flag=true,dfs1(v,p),f[p]+=min(e[i].c,f[v]);
}
if(!flag)f[p]=0x3f3f3f3f;
}
void dfs2(int p,int fa){
for (int i=first[p];i;i=e[i].next){
int v=e[i].v;
if(v==fa)continue;
if(f[v]!=0x3f3f3f3f)ans=max(ans,(g[v]=f[v]+min(g[p]-min(e[i].c,f[v]),e[i].c))),dfs2(v,p);
}
}
int main(){
n=read();
for(int u,v,c,i=1;i<n;++i)u=read(),v=read(),c=read(),add(u,v,c),add(v,u,c);
dfs1(1,0),g[1]=ans=f[1],dfs2(1,0),cout<<ans;
return 0;
}