码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ1812 [IOI2005]river

时间:2016-09-06 13:45:21      阅读:148      评论:0      收藏:0      [点我收藏+]

标签:

传送门:

很常规的一道树规,转为左儿子右兄弟。

然后f[node][anc][K]表示在node节点上,最近的有贡献祖先在anc上,在node的儿子和兄弟上有k个有贡献节点的最优值。

然后得出以下转移方程。

f[node][anc][K]=min{f[son[node]][anc][k]+f[bro[node]][anc][K-k]}+Value[node]*(dis[node]-dis[anc]); 无贡献

f[node][anc][K]=min{f[son[node]][node][k]+f[bro[node]][anc][K-1-k]}                                              有贡献

 

下面是代码实现:

技术分享
 1 //BZOJ 1812
 2 //by Cydiater
 3 //2016.9.5
 4 #include <iostream>
 5 #include <cstdio>
 6 #include <cstdlib>
 7 #include <cstring>
 8 #include <string>
 9 #include <algorithm>
10 #include <queue>
11 #include <map>
12 #include <ctime>
13 #include <cmath>
14 #include <iomanip>
15 using namespace std;
16 #define ll long long
17 #define up(i,j,n)        for(int i=j;i<=n;i++)
18 #define down(i,j,n)        for(int i=j;i>=n;i--)
19 const int MAXN=105;
20 const int oo=0x3f3f3f3f;
21 inline int read(){
22     char ch=getchar();int x=0,f=1;
23     while(ch>9||ch<0){if(ch==-)f=-1;ch=getchar();}
24     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
25     return x*f;
26 }
27 int N,K,son[MAXN],bro[MAXN],Value[MAXN],dis[MAXN],LINK[MAXN],len=0,fa[MAXN],f[MAXN][MAXN][MAXN],pre_fa[MAXN];
28 struct edge{
29     int y,next,v;
30 }e[MAXN<<1];
31 namespace solution{
32     inline void insert(int x,int y,int v){e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;e[len].v=v;}
33     void dfs(int node){
34         for(int i=LINK[node];i;i=e[i].next){
35             dis[e[i].y]=dis[node]+e[i].v;
36             dfs(e[i].y);
37         }
38     }
39     void init(){
40         N=read();K=read();
41         pre_fa[0]=-1;
42         up(i,1,N){
43             Value[i]=read();int y=read(),v=read();
44             pre_fa[i]=y;
45             insert(y,i,v);
46         }
47         dfs(0);dis[0]=0;
48     }
49     void build(int node,int father){
50         int tmp=LINK[node];son[node]=e[tmp].y;fa[node]=father;
51         if(tmp)build(e[tmp].y,node);node=e[tmp].y;
52         for(int i=e[tmp].next;i;i=e[i].next){
53             bro[node]=e[i].y;build(e[i].y,node);
54             node=e[i].y;
55         }
56     }
57     void TreeDP(int node){
58         if(son[node])TreeDP(son[node]);
59         if(bro[node])TreeDP(bro[node]);
60         int father=pre_fa[node];
61         while(father!=-1){
62             up(lim,0,K)up(k,0,lim){
63                 int tmp=Value[node]*(dis[node]-dis[father]);
64                 if(son[node])tmp+=f[son[node]][father][k];
65                 if(bro[node])tmp+=f[bro[node]][father][lim-k];
66                 f[node][father][lim]=min(f[node][father][lim],tmp);
67             }
68             up(lim,1,K)up(k,1,lim){
69                 int tmp=0;
70                 if(son[node])tmp+=f[son[node]][node][k-1];
71                 if(bro[node])tmp+=f[bro[node]][father][lim-k];
72                 f[node][father][lim]=min(f[node][father][lim],tmp);
73             }
74             father=pre_fa[father];
75         }
76         if(node==0){
77             father=0;
78             up(lim,0,K)up(k,0,lim){
79                 int tmp=0;
80                 if(son[node])tmp+=f[son[node]][father][k];
81                 if(bro[node])tmp+=f[bro[node]][father][lim-k];
82                 f[node][father][lim]=min(f[node][father][lim],tmp);
83             }
84         }
85     }
86     void slove(){
87         build(0,-1);
88         memset(f,0x3f,sizeof(f));
89         TreeDP(0);
90         printf("%d\n",f[0][0][K]);
91     }
92 }
93 int main(){
94     //freopen("input.in","r",stdin);
95     using namespace solution;
96     init();
97     slove();
98     return 0;
99 }
View Code

 

BZOJ1812 [IOI2005]river

标签:

原文地址:http://www.cnblogs.com/Cydiater/p/5845230.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!