zxa and leaf
zxa有一棵含有n個節點的無根樹,包含(n−1)條無向邊,點從1到n編號,定義每個點的度數爲與這個點相連的邊的數量,度數爲1的節點被稱作這棵樹的葉子節點。 zxa想給每個節點設置它的好看度,好看度必須爲正整數。他的無根樹有m(1≤m≤n)個葉子節點,其中的k(1≤k≤m)個葉子節點的好看度已經確定,zxa只需要設置其他節點的好看度。 zxa很好奇,如果令每條邊的難看度是這條邊所連接的兩個節點的好看度差值的絕對值,整棵樹的難看度是所有邊的難看度中的最大值,那麼這棵樹的難看度最小是多少,你能幫助他嗎?
第一行有一個正整數T,表示有T組數據。 對於每組數據: 第一行有兩個正整數n和k,表示這棵樹有n個節點,其中k個葉子節點的好看度已經確定。 接下來(n−1)行,每行有兩個互異的正整數u和v,表示節點u和節點v之間有一條無向邊。 接下來k行,每行有兩個正整數u和w,表示節點u是葉子節點,而且它的好看度是w。 每一行相鄰數字之間只有一個空格。 保證輸入的邊構成一棵樹。 1≤T≤10,2≤n≤5⋅104,1≤k≤n,1≤u,v≤n,1≤w≤109
對於每組數據,輸出一行,包含一個非負整數,表示這棵樹的難看度最小值。
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
如果你需要更大的棧空間,請使用#pragma comment(linker, "/STACK:102400000,102400000")並且選擇使用C++提交你的代碼。
所以總結一下這個題,一開始沒思路,是因爲二分根本抓瞎,太弱沒想到。後來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;
}