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⋅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
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;
}
相关文章推荐
- 数据库范式
- 握手,交流从掌心开始
- PHP AJAX 返回JSON 数据
- [转]原码, 反码, 补码 详解 很全
- SDUT2087离散事件模拟-银行管理
- 类和指针
- java知识点及初学类
- Python处理Excel(五):读取Excel中的Int型数
- Java单例模式详解
- redis windows下的环境搭建
- DP——最优矩阵链乘&&最优三角剖分
- [树形DP 启发式合并 神题] BZOJ 4543 [POI2014]Hotel加强版 & BZOJ 3522 [Poi2014]Hotel
- DNA比对(DP)
- SSH中为什么action需要用多例而dao层和service层为什么就用单例就可以
- zabbix3.0.2 使用percona的mysql插件的遇到的诡异问题解决记录
- C++中JSON文件的读取
- 一个屌丝程序猿的人生(十)
- Ex2010-13 Configuring outlook anywhere
- 练习1-10 人生若只如初见,何事秋风悲画扇
- mac下go环境配置