您的位置:首页 > 其它

HDU 5682:zxa and leaf 二分

2016-05-18 21:33 337 查看


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)(n−1)条无向边,点从11到nn编号,定义每个点的度数为与这个点相连的边的数量,度数为11的节点被称作这棵树的叶子节点。

zxa想给每个节点设置它的好看度,好看度必须为正整数。他的无根树有m(1\leq m\leq n)m(1≤m≤n)个叶子节点,其中的k(1\leq k\leq m)k(1≤k≤m)个叶子节点的好看度已经确定,zxa只需要设置其他节点的好看度。

zxa很好奇,如果令每条边的难看度是这条边所连接的两个节点的好看度差值的绝对值,整棵树的难看度是所有边的难看度中的最大值,那么这棵树的难看度最小是多少,你能帮助他吗?

输入描述
第一行有一个正整数TT,表示有TT组数据。

对于每组数据:

第一行有两个正整数nn和kk,表示这棵树有nn个节点,其中kk个叶子节点的好看度已经确定。

接下来(n-1)(n−1)行,每行有两个互异的正整数uu和vv,表示节点uu和节点vv之间有一条无向边。

接下来kk行,每行有两个正整数uu和ww,表示节点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^91≤T≤10,2≤n≤5⋅10​4​​,1≤k≤n,1≤u,v≤n,1≤w≤10​9​​

输出描述
对于每组数据,输出一行,包含一个非负整数,表示这棵树的难看度最小值。

输入样例
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: