注意不能只是判断根节点的minn,maxx值大小,而是要判断所有节点的该值大小,有一个不合法就得返回是0,否则就wrong,也就是中间那句if(!dfs()) 特别重要!
正着反着都要去想一想
#include<iostream>
#include<cstdio>
#include<string.h>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
#define ll long long
#pragma comment(linker, "/STACK:102400000,102400000")
const int maxn=5e4+10;
int t,n,k,u,v;
vector<int>a[maxn];
int degree[maxn];int op[maxn];
int minn[maxn],maxx[maxn],vis[maxn];
int dfs(int u,int val){
minn[u]=-(int)1e9;maxx[u]=(int)1e9;
if(op[u]){
minn[u]=op[u];maxx[u]=op[u];
}
for(int i = 0; i < a[u].size(); i++){
int v = a[u][i];if(vis[v]) continue;
vis[v] = 1;
// cout<<" u = "<<u<<" v = "<<v<<endl;
if(!dfs(v,val)) return 0 ;
maxx[u] = min(maxx[u] , maxx[v] + val);
minn[u] = max(minn[u], minn[v] - val);
}
// if(val == 3 && u == 1){
// cout<<" u = "<<u<<" maxx = "<<maxx[u]<<" minn = "<<minn[u]<<endl;
// }
return maxx[u] >= minn[u];
}
int main(){
cin>>t;
while(t--){
//memset(degree,0,sizeof(degree));
scanf("%d%d",&n,&k);
for(int i = 1;i <= n;i ++) {
a[i].clear();op[i] = 0 ;degree[i] = 0;
}
for(int i = 1 ;i <= n - 1 ;i ++){
scanf("%d %d",&u,&v);
a[u].push_back(v);a[v].push_back(u);
degree[u]++;degree[v]++;
}
for(int i = 1; i <= k;i ++){
scanf("%d%d",&u,&v);
op[u] = v;
}
if(n == 2){
cout<<abs(op[1]-op[2])<<endl;continue;
}
int root = 0;
for(int i = 1;i <= n;i ++){
if(degree[i] != 1){
root = i;break;
}
}
// cout<<" root= "<<root <<endl;
// vis[root] = 1;
// puts("niin");
int l = -1 ; int r = (int)1e9+1;
// cout<<" r= "<<r<<endl;
while(l + 1 < r ){
int mid = (l + r) / 2;
memset(vis,0,sizeof(vis));
vis[root] = 1;
// cout<<"root = "<<root<<endl;
// cout<<" mid = "<<mid<<endl;
//memset(maxx,0,sizeof(maxx));
if(dfs(root ,mid )){
r = mid ;//cout<<"bingo"<<endl;
}
else l = mid ;
// system("pause");
}
printf("%d\n",r);
}
}