给定一个n个点的有根树。有m个旅客,第i个旅客打算从1走到Bi,预算为Ci,如果花费大于预算就会放弃前往。要求给每条边设一个过路费,最大化收益(SPJ)。
比赛的时候bblss123想出来了,但因为我们的失误怠慢了她它==,然后她它就睡觉去了,不然真能抢到First Blood==。
dp[i][j] :1(根节点)到i的花费为j为hash[j]时i的子树中最大收益
dp[i][j]=hash[j]∗(目的地为i点,预算>=hash[j]的旅客数)+∑s∈son(i)max(dp[s][k],k≥j) .
然后单调处理一下就好了,难怪大家都懒得写==
树形dp
#include <set>
#include <ctime>
#include <queue>
#include <cstdio>
#include <bitset>
#include <cctype>
#include <bitset>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <iostream>
#include <algorithm>
#define inf (1<<30)
#define INF (1ll<<62)
#define fi first
#define se second
#define rep(x,s,t) for(register int x=s,t_=t;x<t_;++x)
#define per(x,s,t) for(register int x=t-1,s_=s;x>=s_;--x)
#define prt(x) cout<<#x<<":"<<x<<" "
#define prtn(x) cout<<#x<<":"<<x<<endl
#define travel(x) for(int I=last[x],to;(~I)&&(to=e[I].to);I=e[I].nxt)
#define pb(x) push_back(x)
#define hash asfmaljkg
#define rank asfjhgskjf
#define y1 asggnja
#define y2 slfvm
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
template<class T>void sc(T &x){
int f=1;char c;x=0;
while(c=getchar(),c<48)if(c=='-')f=-1;
do x=x*10+(c^48);
while(c=getchar(),c>47);
x*=f;
}
template<class T>void nt(T x){
if(!x)return;
nt(x/10);
putchar(x%10+'0');
}
template<class T>void pt(T x){
if(x<0)putchar('-'),x=-x;
if(!x)putchar('0');
else nt(x);
}
template<class T>void ptn(T x){
pt(x);putchar('\n');
}
template<class T>void pts(T x){
pt(x);putchar(' ');
}
template<class T>inline void Max(T &x,T y){if(x<y)x=y;}
template<class T>inline void Min(T &x,T y){if(x>y)x=y;}
int n,m;
const int maxn=1005;
int has[maxn],tot;
int last[maxn],ecnt;
struct Edge{
int to,nxt;
}e[maxn<<1];
int val[maxn];
void ins(int u,int v){
e[ecnt]=(Edge){v,last[u]};
last[u]=ecnt++;
}
int sz[maxn],bag[maxn][maxn];
int tar[maxn],hav[maxn];
ll dp[maxn][maxn];
//dp[i][j]:1到i的代价为has[j]时的最大收益
void dfs(int x,int f){
travel(x)if(to^f)dfs(to,x);
int top=sz[x];
per(i,0,tot+1){
while(top&&bag[x][top-1]>=i)top--;
dp[x][i]=1ll*has[i]*(sz[x]-top);
travel(x)if(to^f)
dp[x][i]+=dp[to][i];
if(i<tot)Max(dp[x][i],dp[x][i+1]);
}
}
void rdfs(int x,int cost,int f){
travel(x)if(to^f){
int j;
for(j=cost;j<=tot&&dp[to][j]==dp[to][cost];j++);
--j;
val[I>>1]=has[j]-has[cost];
rdfs(to,j,x);
}
}
void solve(){
sc(n);sc(m);
memset(last,-1,n+1<<2);
ecnt=0;
rep(i,1,n){
int u,v;
sc(u);sc(v);
ins(u,v);
ins(v,u);
}
tot=0;
rep(i,1,m+1){
sc(tar[i]),sc(hav[i]);
if(tar[i]==1)hav[i]=0;
has[++tot]=hav[i];
}
sort(has+1,has+tot+1);
tot=unique(has+1,has+tot+1)-has-1;
memset(sz,0,n+1<<2);
rep(i,1,m+1){
hav[i]=lower_bound(has+1,has+tot+1,hav[i])-has;
bag[tar[i]][sz[tar[i]]++]=hav[i];
}
rep(i,1,n+1)sort(bag[i],bag[i]+sz[i]);
dfs(1,0);
ptn(dp[1][0]);
rdfs(1,0,0);
rep(i,0,n-2)pts(val[i]);
ptn(val[n-2]);
}
int main(){
// freopen("pro.in","r",stdin);
// freopen("chk.out","w",stdout);
int cas;sc(cas);
while(cas--)solve();
return 0;
}