标签:
2 5 \ / 3 4 \ / 1 |
input | output |
---|---|
5 2 1 3 1 1 4 10 2 3 20 3 5 20 |
21 |
题目大意:n个点 n-1条边,现在要保留Q条边,求保留下的边的去权值和的最大值。
把边的权值映射到点上,边的权值相当于这个点指向根节点的权值,所以问题转换成对点的操作。
先统计出以当前点为根节点的子树的点数(包括当前根节点),然后dp,
这里dp,以u为根节点保留j个点能得到最大值,状态转移方程
dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v]k]+val)
val是v到u的权值。
/* *********************************************** Author :guanjun Created Time :2016/10/15 15:43:48 File Name :timus1018.cpp ************************************************ */ #include <bits/stdc++.h> #define ull unsigned long long #define ll long long #define mod 90001 #define INF 0x3f3f3f3f #define maxn 10010 #define cle(a) memset(a,0,sizeof(a)) const ull inf = 1LL << 61; const double eps=1e-5; using namespace std; priority_queue<int,vector<int>,greater<int> >pq; struct Node{ int x,y; }; struct cmp{ bool operator()(Node a,Node b){ if(a.x==b.x) return a.y> b.y; return a.x>b.x; } }; bool cmp(int a,int b){ return a>b; } struct node{ int y; int val; }; vector<node>v[110]; int sz[110],n,m,num; int dp[110][110]; void dfs(int u,int fa){ num++; sz[u]=1; for(int i=0;i<v[u].size();i++){ int y=v[u][i].y; if(y==fa)continue; dfs(y,u); sz[u]+=sz[y]; } } void dfs2(int u,int fa){ for(int i=0;i<v[u].size();i++){ int y=v[u][i].y; int val=v[u][i].val; if(y==fa)continue; //cout<<u<<" "<<sz[u]<<endl; dfs2(y,u); for(int j=sz[u];j>1;j--){ for(int k=1;k<j;k++){ dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[y][k]+val); } } } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif //freopen("out.txt","w",stdout); while(cin>>n>>m){ num=0; int x,y,z; cle(sz); for(int i=1;i<n;i++){ cin>>x>>y>>z; v[x].push_back({y,z}); v[y].push_back({x,z}); } cle(dp); dfs(1,-1); dfs2(1,-1); cout<<dp[1][m+1]<<endl; } return 0; }
标签:
原文地址:http://www.cnblogs.com/pk28/p/5965251.html