二分+树型 dp hdu5682 zxa and leaf

来源:互联网 发布:林俊杰 睡粉 知乎 编辑:程序博客网 时间:2024/06/07 05:15

传送门:点击打开链接

题意:一棵树n个点,其中有一些点已经有权值,现在给剩下的点安排权值,使得树中相邻两点的之差绝对值的最大值最小。

思路:如果我们首先就想到了二分,那后面很好想了。。

直接二分答案,之后check中,我们随便取1个点为根节点,然后从下向上按拓扑序做树型dp。设SL[u]和SR[u]表示节点u能填的数字的范围

我们从下往上,然后只要判断是否有交集,即有解,我们就能知道当前答案是否可以使用了。

Trick:下次再用G++交用了#prama扩栈的代码剁手。。

#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\n", solve());    }    return 0;}


0 0
原创粉丝点击