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;
}

浙公网安备 33010602011771号