HDU 5682:zxa and leaf 二分

zxa and leaf

 
 Accepts: 25
 
 Submissions: 249
 Time Limit: 5000/2500 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
問題描述
zxa有一棵含有nn個節點的無根樹,包含(n-1)(n1)條無向邊,點從11nn編號,定義每個點的度數爲與這個點相連的邊的數量,度數爲11的節點被稱作這棵樹的葉子節點。

zxa想給每個節點設置它的好看度,好看度必須爲正整數。他的無根樹有m(1\leq m\leq n)m(1mn)個葉子節點,其中的k(1\leq k\leq m)k(1km)個葉子節點的好看度已經確定,zxa只需要設置其他節點的好看度。

zxa很好奇,如果令每條邊的難看度是這條邊所連接的兩個節點的好看度差值的絕對值,整棵樹的難看度是所有邊的難看度中的最大值,那麼這棵樹的難看度最小是多少,你能幫助他嗎?
輸入描述
第一行有一個正整數TT,表示有TT組數據。

對於每組數據:

第一行有兩個正整數nnkk,表示這棵樹有nn個節點,其中kk個葉子節點的好看度已經確定。

接下來(n-1)(n1)行,每行有兩個互異的正整數uuvv,表示節點uu和節點vv之間有一條無向邊。

接下來kk行,每行有兩個正整數uuww,表示節點uu是葉子節點,而且它的好看度是ww。

每一行相鄰數字之間只有一個空格。

保證輸入的邊構成一棵樹。

1\leq T\leq 10,2\leq n\leq 5\cdot10^4,1\leq k\leq n,1\leq u,v\leq n,1\leq w\leq 10^91T10,2n5104,1kn,1u,vn,1w109
輸出描述
對於每組數據,輸出一行,包含一個非負整數,表示這棵樹的難看度最小值。
輸入樣例
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
輸出樣例
3
1
Hint
如果你需要更大的棧空間,請使用#pragma comment(linker, "/STACK:102400000,102400000")並且選擇使用C++提交你的代碼。
這個題其實考慮到二分,也就可以出了,每個點有自己的一個取值區間,然後如果這個mid能夠滿足所有點的取值區間,就ok。

所以總結一下這個題,一開始沒思路,是因爲二分根本抓瞎,太弱沒想到。後來RE,是因爲沒有考慮到兩個點的情況,兩個點的話都是葉子節點了,這種情形要考慮到。最後wa的原因是在INF,要設置成1e9就夠了,之前設置的太大,導致爆了int。

代碼:

#pragma comment(linker, "/STACK:102400000,102400000") 
#pragma warning(disable:4996)
#include <fstream>
#include <iostream>
#include <functional>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <map>
using namespace std;
typedef long long ll;

#define INF 1e9 + 1
#define mem(a, b) memset(a, b, sizeof(a))
#define pper(i,n,m) for(int i = n;i >= m; i--)
#define repp(i, n, m) for (int i = n; i <= m; i++)
#define rep(i, n, m) for (int i = n; i < m; i++)
#define sa(n) scanf("%d", &(n))
#define mp make_pair
#define ff first
#define ss second
#define pb push_back

const int maxn = 1e5 + 5;
const ll mod = 1e9 + 7;
const double PI = acos(-1.0);

struct ed
{
    int to;
    int next;
}edge[maxn * 2];

int n, k, f, edgen, mid;
int head[maxn], vis[maxn], leaf[maxn], val[maxn], out[maxn];

pair<int, int>dfs(int x)
{
    if (f == 0)
        return mp(0, 0);
    vis[x] = 1;

    int i, j;
    int ri = INF, le = -INF;
    if (leaf[x] == 1)
    {
        le = ri = val[x];
    }
    for (i = head[x]; i != -1; i = edge[i].next)
    {
        int to = edge[i].to;
        if (vis[to] == 0)
        {
            pair<int, int>s = dfs(to);
            if (s.ff == -INF)
                continue;
            le = max(le, s.ff - mid);
            ri = min(ri, s.ss + mid);
            if (le > ri)
            {
                f = 0;
                return mp(0, 0);
            }
        }
    }

    return mp(le, ri);
}

void init()
{
    edgen = 0;
    memset(head, -1, sizeof(head));
    memset(edge, -1, sizeof(edge));
    memset(leaf, 0, sizeof(leaf));
    memset(val, 0, sizeof(val));
    memset(out, 0, sizeof(out));
}

void addedge(int u, int v)
{
    edgen++;
    edge[edgen].to = v;
    edge[edgen].next = head[u];
    head[u] = edgen;
}

void solve()
{
    int i, j;
    int u, v;
    sa(n), sa(k);
    repp(i, 1, n - 1)
    {
        sa(u), sa(v);
        addedge(u, v);
        addedge(v, u);
        out[u]++;
        out[v]++;
    }
    repp(i, 1, k)
    {
        sa(u), sa(v);
        leaf[u] = 1;
        val[u] = v;
    }
    int root, le, ri;
    if (n == 2)
    {
        root = 1;
    }
    else
    {
        repp(i, 1, n)
        {
            if (out[i] > 1)
            {
                root = i;
                break;
            }
        }
    }
    ri = INF, le = 0;
    while (le < ri)
    {
        mid = (ri + le) / 2;
        f = 1;
        memset(vis, 0, sizeof(vis));
        dfs(root);
        if (f)
        {
            ri = mid;
        }
        else
        {
            le = mid + 1;
        }
    }
    printf("%d\n", ri);
}

int main()
{
#ifndef ONLINE_JUDGE  
    freopen("i.txt", "r", stdin);
    freopen("o.txt", "w", stdout);
#endif

    int t;
    sa(t);
    while (t--)
    {
        init();
        solve();
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章