8.10-Day2T3 镇守府
emm
IOI原题(洛谷,bzoj都有)
其实并没有怎么搞懂dp方程转移那部分
就...粘个(抄来的)代码过来吧
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; inline int read() { int sum = 0,p = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') p = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (sum *= 10) += ch - '0'; ch = getchar(); } return sum * p; } const int N = 205,M = 55; const int inf = 0x3f3f3f3f; int n,m,head[N],w[N],f[N],cnt; int dis[N][N],dp[N][M][N]; struct edge { int nxt,to; }e[N]; void add(int a,int b) { e[++cnt].nxt = head[a]; e[cnt].to = b; head[a] = cnt; } void dfs(int u) { for(int last = u,i = f[u]; i != -1; i = f[i]) { dis[u][i] = dis[u][last] + dis[last][i]; last = i; } for(int i = head[u]; i; i = e[i].nxt) dfs(e[i].to); } void tree_dp(int u) { bool flag = true; for(int i = head[u]; i; i = e[i].nxt) { flag = false; tree_dp(e[i].to); } if(flag) { for(int i = f[u]; i != -1; i = f[i]) dp[u][0][i] = dis[u][i] * w[u]; return; } if(u != 0) dp[u][0][u] = inf; for(int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; for(int p = f[u]; p != -1; p = f[p]) { for(int j = m; j >= 0; j--) { int tmp = inf; for(int k = 0; k <= j; k++) tmp = min(tmp,dp[u][k][p] + dp[v][j - k][p]); dp[u][j][p] = tmp; } } for(int j = m; j >= 0; j--) { int tmp = inf; for(int k = (u != 0); k <= j; k++) tmp = min(tmp,dp[u][k][u] + dp[v][j - k][u]); dp[u][j][u] = tmp; } } for(int p = f[u]; p != -1; p = f[p]) for(int i = 0; i <= m; i++) { dp[u][i][p] += dis[u][p]*w[u]; dp[u][i][p] = min(dp[u][i][p],dp[u][i][u]); } } int main() { freopen("riv.in","r",stdin); freopen("riv.out","w",stdout); n = read(),m = read(); for(int i = 1; i <= n; i++) { w[i] = read(); f[i] = read(); dis[i][f[i]] = read(); add(f[i],i); } f[0] = -1; dfs(0); tree_dp(0); printf("%d\n",dp[0][m][0]); return 0; }