BZOJ4711 小奇挖矿
Description
【题目背景】
小奇在喵星系使用了无限非概率驱动的采矿机,以至于在所有星球上都采出了一些矿石,现在它准备建一些矿石仓
库并把矿石运到各个仓库里。
【问题描述】
喵星系有n个星球,标号为1到n,星球以及星球间的航线形成一棵树。所有星球间的双向航线的长度都为1。小奇要
在若干个星球建矿石仓库,设立每个仓库的费用为K。对于未设立矿石仓库的星球,设其到一个仓库的距离为i,则
将矿石运回的费用为Di。请你帮它决策最小化费用。
Input
第一行2个整数n,K。
第二行n-1个整数,D1,D2,…Dn-1,保证Di<=Di+1。
接下来n-1行,每行2个整数x,y,表示星球x和星球y存在双向航线。
n<=200,0<=K,Di<=100000
Output
输出一行一个整数,表示最小费用。
Sample Input
8 10
2 5 9 11 15 19 20
1 4
1 3
1 7
4 6
2 8
2 3
3 5
2 5 9 11 15 19 20
1 4
1 3
1 7
4 6
2 8
2 3
3 5
Sample Output
38
【样例解释】
在1,2号星球建立仓库。
【样例解释】
在1,2号星球建立仓库。
令$f[i][j]$表示$i$的子树已经计算离$i$最近的仓库为$j$,且还没有算上建造的方案
一个儿子有2种情况;
1.最近的是k
2.最近的是j
写出来就是
$f[x][i]=min(f[v][j]+k,f[v][i])$
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 struct Node 8 { 9 int next,to; 10 }edge[200001]; 11 int num,head[21],cnt,tot,q[21],p[21],dep[21],fa[21],size[21],son[21],top[21]; 12 int dfn[21],n,k,d[21],ans,Min,sum,f[201][201],dis[201][201]; 13 void add(int u,int v) 14 { 15 num++; 16 edge[num].next=head[u]; 17 head[u]=num; 18 edge[num].to=v; 19 } 20 void dfs1(int x,int pa) 21 {int i; 22 dep[x]=dep[pa]+1; 23 fa[x]=pa; 24 size[x]=1; 25 for (i=head[x];i;i=edge[i].next) 26 { 27 int v=edge[i].to; 28 if (v==pa) continue; 29 dfs1(v,x); 30 size[x]+=size[v]; 31 if (size[v]>size[son[x]]) son[x]=v; 32 } 33 } 34 void dfs2(int x,int pa,int tp) 35 {int i; 36 top[x]=tp; 37 dfn[x]=++tot; 38 if (son[x]) dfs2(son[x],x,tp); 39 for (i=head[x];i;i=edge[i].next) 40 { 41 int v=edge[i].to; 42 if (v==pa||son[x]==v) continue; 43 dfs2(v,x,v); 44 } 45 } 46 int lca(int x,int y) 47 { 48 int as=0; 49 while (top[x]!=top[y]) 50 { 51 if (dep[top[x]]<dep[top[y]]) swap(x,y); 52 x=fa[top[x]]; 53 } 54 if (dep[x]>dep[y]) swap(x,y); 55 return x; 56 } 57 int get_dis(int x,int y) 58 { 59 return dep[x]+dep[y]-2*dep[lca(x,y)]; 60 } 61 void dfs(int x,int pa) 62 {int i,j; 63 for (i=1;i<=n;i++) 64 f[x][i]=d[dis[x][i]]; 65 for (i=head[x];i;i=edge[i].next) 66 { 67 int v=edge[i].to; 68 if (v==pa) continue; 69 dfs(v,x); 70 int as=2e9; 71 for (j=1;j<=n;j++) 72 as=min(as,f[v][j]+k); 73 for (j=1;j<=n;j++) 74 f[x][j]+=min(as,f[v][j]); 75 } 76 } 77 int main() 78 {int i,u,v,j; 79 cin>>n>>k; 80 for (i=1;i<=n-1;i++) 81 { 82 scanf("%d",&d[i]); 83 } 84 for (i=1;i<=n-1;i++) 85 { 86 scanf("%d%d",&u,&v); 87 add(u,v);add(v,u); 88 } 89 dfs1(1,0); 90 dfs2(1,0,1); 91 for (i=1;i<=n;i++) 92 { 93 for (j=1;j<=n;j++) 94 { 95 dis[i][j]=get_dis(i,j); 96 } 97 } 98 dfs(1,0); 99 ans=2e9; 100 for (i=1;i<=n;i++) 101 ans=min(ans,f[1][i]+k); 102 cout<<ans; 103 }