一、题目回顾
题目链接:zxa and leaf
Sample Input
2
3 2
1 2
1 3
2 4
3 9
6 2
1 2
1 3
1 4
2 5
2 6
3 6
5 9
Sample Output
3
1
Hint
If you need a larger stack size, please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.
题意:一棵树n个点,其中有一些点已经有权值,现在给剩下的点安排权值,使得树中相邻两点的之差绝对值的最大值最小。
二、解题思路
- 二分+树形dp(也可以二分+dfs)
思路:如果我们首先就想到了二分,那后面很好想了。。
直接二分答案,之后check中,我们随便取1个点为根节点,然后从下向上按拓扑序做树型dp。设SL[u]和SR[u]表示节点u能填的数字的范围
我们从下往上,然后只要判断是否有交集,即有解,我们就能知道当前答案是否可以使用了。
三、代码
#include <map> #include <set> #include <cmath> #include <ctime> #include <stack> #include <queue> #include <cstdio> #include <cctype> #include <bitset> #include <string> #include <vector> #include <cstring> #include <iostream> #include <algorithm> #include <functional> #define fuck(x) cout<<"["<<x<<"]"; #define FIN freopen("input.txt","r",stdin); #define FOUT freopen("output.txt","w+",stdout); #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; typedef long long LL; typedef pair<int, int> PII; const int MX = 1e5 + 5; const LL INF = 0x3f3f3f3f3f3f3f3fLL; struct Edge { int nxt, v; } E[MX]; int Head[MX], erear; void edge_init() { erear = 0; memset(Head, -1, sizeof(Head)); } void edge_add(int u, int v) { E[erear].v = v; E[erear].nxt = Head[u]; Head[u] = erear++; } int is[MX], val[MX]; LL SL[MX], SR[MX]; bool DFS(int u, int f, int x) { if(is[u]) SL[u] = SR[u] = val[u]; else SL[u] = -INF, SR[u] = INF; for(int i = Head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if(v == f) continue; if(!DFS(v, u, x)) return false; if(SL[v] != INF) SL[u] = max(SL[u], SL[v] - x); if(SR[v] != INF) SR[u] = min(SR[u], SR[v] + x); } if(SL[u] > SR[u]) return false; return true; } int solve() { int l = 0, r = 1e9, m; while(l <= r) { m = (l + r) >> 1; if(DFS(1, -1, m)) r = m - 1; else l = m + 1; } return r + 1; } int main() { int T, n, k; //FIN; scanf("%d", &T); while(T--) { edge_init(); scanf("%d%d", &n, &k); for(int i = 1; i <= n; i++) is[i] = 0; for(int i = 1; i <= n - 1; i++) { int u, v; scanf("%d%d", &u, &v); edge_add(u, v); edge_add(v, u); } for(int i = 1; i <= k; i++) { int u, w; scanf("%d%d", &u, &w); is[u] = 1; val[u] = w; } printf("%d ", solve()); } return 0; }