洛谷P1273 有线电视网 树上分组背包DP

时间:2020-12-02 23:05:58

P1273 有线电视网

)逼着自己写DP

题意:在一棵树上选出最多的叶子节点,使得叶子节点的值 减去 各个叶子节点到根节点的消耗 >= 0;

思路:

  树上分组背包DP,设dp[u][k] 表示 到以u节点为根节点选k个叶子能得到的最大值。则可得到状态转移方程,

  dp[u][k] = max(dp[u][k], dp[u][k-t] + dp[v][t] - cost),其中的t表示不同的可能,需要枚举。

#include <algorithm>
#include <iterator>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <stack>
#include <cmath>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <cassert> using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3; //priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '\n' #define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A) //用来压行
#define REP(i , j , k) for(int i = j ; i < k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que; const ll mos = 0x7FFFFFFF; //
const ll nmos = 0x80000000; //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //
const int mod = 1e9+;
const double esp = 1e-;
const double PI=acos(-1.0);
const double PHI=0.61803399; //黄金分割点
const double tPHI=0.38196601; template<typename T>
inline T read(T&x){
x=;int f=;char ch=getchar();
while (ch<''||ch>'') f|=(ch=='-'),ch=getchar();
while (ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
return x=f?-x:x;
} /*-----------------------showtime----------------------*/
const int maxn = ;
vector<pii>mp[maxn];
int n,m;
int dp[maxn][maxn],a[maxn];
int dfs(int u, int fa){
int res = ; if(mp[u].size() == ) { dp[u][] = a[u];
return ; }
for(int i=; i<mp[u].size(); i++){
int v = mp[u][i].fi;
if(v == fa) continue; res += dfs(v, u);
dp[u][] = ;
for(int j=res; j >= ; j--){
for(int k=; k<=j; k++){
dp[u][j] = max(dp[u][j], dp[u][j-k] + dp[v][k] - mp[u][i].se);
}
}
}
return res;
} int main(){
scanf("%d%d", &n, &m);
memset(dp, ~inf, sizeof(dp)); for(int i=; i<=n-m; i++){
int k; scanf("%d", &k);
for(int j=; j<=k; j++) {
int v,w;
scanf("%d%d", &v, &w);
mp[i].pb(pii(v,w));
}
}
for(int i=n-m+; i<=n; i++) scanf("%d", &a[i]); int tmp = dfs(,-);
for(int i=tmp; i>=; i--) {
if(dp[][i] >= ) {
printf("%d\n", i);
return ;
}
}
return ;
}