T - zxa and leaf
题目大意是:给你一颗树,这棵树有些节点已经设置了它的美丽值,然后剩下一些节点需要我们设置美丽值。
一条边的丑陋程度等于被定义为由这个边缘连接的两个节点之间的美丽水平的绝对差异
一棵树的丑陋程度则是边的丑陋程度的最大值。
这个题目应该是二分这个丑陋值。
然后dfs来判断这个丑陋值是不是合理。
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <map> #include <queue> #include <vector> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int INF = 0x3f3f3f3f; const int maxn = 1e5 + 10; vector<int>G[maxn]; ll lc[maxn], rc[maxn], el[maxn], er[maxn]; bool dfs(int u,int pre,int x) { //printf("u=%d pre=%d x=%d ", u, pre, x); int flag = 1; for(int i=0;i<G[u].size();i++) { int v = G[u][i]; if (v == pre) continue; if (lc[v] == 0 && rc[v] == 0) { lc[v] = max(1ll * 0, lc[u] - x); rc[v] = rc[u] + x; } else { ll val = lc[v]; if ((val <= rc[u] && val >= lc[u])) { rc[u] = min(rc[u], val + x); lc[u] = max(val - x, lc[u]); } else if (abs(val - lc[u]) <= x || abs(val - rc[u]) <= x) { if (val >= rc[u]) lc[u] = max(lc[u], val - x); if (val <= lc[u]) rc[u] = min(rc[u], val + x); if (lc[u] > rc[u]) return false; } else return false; } //printf("lc[%d]=%lld rc[%d]=%lld ", v, lc[v], v, rc[v]); if (dfs(v, u, x) == 0) flag = 0; } return flag; } int main() { int t; scanf("%d", &t); while(t--) { int n, k; memset(el, 0, sizeof(el)); memset(er, 0, sizeof(er)); scanf("%d%d", &n, &k); for (int i = 0; i <= n; i++) G[i].clear(); for (int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } int mark = 0; for (int i = 1; i <= k; i++) { int u, w; scanf("%d%d", &u, &w); mark = u; el[u] = er[u] = w; } //printf("mark=%d ", mark); int l = 0, r = 1e9, ans = 0; while(l<=r) { memcpy(lc, el, sizeof(el)); memcpy(rc, er, sizeof(er)); int mid = (l + r) >> 1; if (dfs(mark,-1,mid)) ans = mid, r = mid - 1; else l = mid + 1; //printf("l=%d r=%d mid=%d ans=%d ", l, r, mid, ans); } printf("%d ", ans); } } /* 2 10 4 7 2 1 5 10 2 1 9 5 7 1 8 3 5 4 7 6 8 9 39 6 9 2 26 4 10 */