题意:
思路:令F[i][j]表示
的最小费用。Best[i]表示以i为根节点的子树多有节点都找到负责消防站的最小费用。
好难的题。。。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 int tot,go[200005],first[200005],next[200005],val[200005]; 7 int dis[200005],f[2005][2005]; 8 int n,w[200005],d[200005],best[200005]; 9 void insert(int x,int y,int z){ 10 tot++; 11 go[tot]=y; 12 next[tot]=first[x]; 13 first[x]=tot; 14 val[tot]=z; 15 } 16 void add(int x,int y,int z){ 17 insert(x,y,z); 18 insert(y,x,z); 19 } 20 void Dfs(int x){ 21 for (int i=first[x];i;i=next[i]){ 22 int pur=go[i]; 23 if (dis[pur]!=-1) continue; 24 dis[pur]=dis[x]+val[i]; 25 Dfs(pur); 26 } 27 } 28 void dfs(int x,int fa){ 29 for (int i=first[x];i;i=next[i]){ 30 int pur=go[i]; 31 if (pur==fa) continue; 32 dfs(pur,x); 33 } 34 for (int i=1;i<=n;i++) dis[i]=-1; 35 dis[x]=0; 36 Dfs(x);best[x]=99999999; 37 for (int i=1;i<=n;i++) f[x][i]=99999999; 38 for (int i=1;i<=n;i++) 39 if (dis[i]<=d[x]){ 40 f[x][i]=w[i]; 41 for (int j=first[x];j;j=next[j]){ 42 int pur=go[j]; 43 if (pur==fa) continue; 44 f[x][i]+=std::min(best[pur],f[pur][i]-w[i]); 45 } 46 best[x]=std::min(best[x],f[x][i]); 47 } 48 } 49 int main(){ 50 int T; 51 scanf("%d",&T); 52 while (T--){ 53 scanf("%d",&n); 54 for (int i=1;i<=n;i++) scanf("%d",&w[i]); 55 for (int i=1;i<=n;i++) scanf("%d",&d[i]); 56 tot=0; 57 for (int i=1;i<=n;i++) first[i]=0; 58 for (int i=1;i<n;i++){ 59 int x,y,z; 60 scanf("%d%d%d",&x,&y,&z); 61 add(x,y,z); 62 } 63 dfs(1,0); 64 printf("%d\n",best[1]); 65 } 66 }
时间: 2024-10-05 09:10:18