POJ2152 Fire
这是一道dp的题目
dp[i][j]表示如果i地由j地的消防站管的子树最小代价
best[i]表示i点子树的最小代价
dis[i]表示i点到当前点的最小距离
然后best[i]=min(dp[i][j])
dp[i][j]=w[j]+sum(min(best[son],dp[son][j]-w[j]))
转移就行了
还是我太菜了
这种题都不会做
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int MAXN=1005; const int MAXM=2005; const int inf=0x3f3f3f3f; inline int read(){ int x=0,f=1,ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int h[MAXN],nxt[MAXM],to[MAXM],cost[MAXM],cnt; inline void add(int x,int y,int z){ nxt[cnt]=h[x];to[cnt]=y;cost[cnt]=z;h[x]=cnt++; nxt[cnt]=h[y];to[cnt]=x;cost[cnt]=z;h[y]=cnt++; } int w[MAXN],d[MAXN],dp[MAXN][MAXN],dis[MAXN],best[MAXN]; inline void spfa(int x,int fa){ for(int i=h[x];i!=-1;i=nxt[i]) if(to[i]!=fa) dis[to[i]]=dis[x]+cost[i],spfa(to[i],x); } int n; inline void dfs(int x,int fa){ for(int i=h[x];i!=-1;i=nxt[i]) if(to[i]!=fa) dfs(to[i],x); dis[x]=0;spfa(x,-1); best[x]=inf; for(int i=1;i<=n;i++){ if(dis[i]>d[x]) dp[x][i]=inf; else{ dp[x][i]=w[i]; for(int j=h[x];j!=-1;j=nxt[j]) if(to[j]!=fa) dp[x][i]+=min(best[to[j]],dp[to[j]][i]-w[i]); } best[x]=min(best[x],dp[x][i]); } } int main(){ int T=read(); while(T--){ memset(h,-1,sizeof(h)); cnt=0; n=read(); for(int i=1;i<=n;i++) w[i]=read(); for(int i=1;i<=n;i++) d[i]=read(); for(int i=1;i<n;i++){ int x=read(),y=read(),z=read(); add(x,y,z); } dfs(1,-1); printf("%d\n",best[1]); } return 0; }