POJ2152

树形dp,每次先dfs一遍求出距离再枚举所有点转移即可。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
    int x=0,f=1; char 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;
}
#define MAXN 1010
int N,T,d[MAXN],c[MAXN];
struct EdgeNode{int next,to,dis;}edge[MAXN<<1];
int head[MAXN],cnt=1;
int f[MAXN][MAXN],g[MAXN],deep[MAXN];
inline void AddEdge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; edge[cnt].to=v; edge[cnt].dis=w; head[u]=cnt;}
inline void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,w);}
inline void DFS_1(int now,int last)
{
    for (int i=head[now]; i; i=edge[i].next)
        if (edge[i].to!=last)
            deep[edge[i].to]=deep[now]+edge[i].dis,
            DFS_1(edge[i].to,now);
}
inline void DFS_2(int now,int last)
{
    for (int i=head[now]; i; i=edge[i].next)
        if (edge[i].to!=last)
            DFS_2(edge[i].to,now);
    deep[now]=0; DFS_1(now,0);
    for (int j=1; j<=N; j++)
        if (deep[j]<=d[now])
            {
                f[now][j]=c[j];
                for (int i=head[now]; i; i=edge[i].next)
                    if (edge[i].to!=last)
                        f[now][j]+=min(g[edge[i].to],f[edge[i].to][j]-c[j]);
                g[now]=min(g[now],f[now][j]);
            }
}
int main()
{
    T=read();
    while (T--)
        {
            N=read();
            for (int i=1; i<=N; i++) c[i]=read();
            for (int i=1; i<=N; i++) d[i]=read();
            cnt=1; memset(head,0,sizeof(head));
            for (int i=1,x,y,z; i<=N-1; i++) x=read(),y=read(),z=read(),InsertEdge(x,y,z);
            memset(f,63,sizeof(f)); memset(g,63,sizeof(g));
            DFS_2(1,0);
//            for (int i=1; i<=N; i++)
//                for (int j=1; j<=N; j++)
//                    printf("%d %d %d\n",i,j,f[i][j]);
            printf("%d\n",g[1]);
        }
    return 0;
}
POJ2152

相关文章: