[codeforces] Gym - 100814D Frozen Rivers (BFS + 二分)
题目链接:Gym - 100814D Frozen Rivers
题目大意:
给
n
个点, 之后
之后由
q
个询问, 每次询问一个时间
数据范围:
(1<=n<=1e5)(1<=pi<=n)(0<=ci<=1e5)
(1<=q<=1e5)(0<=qi<=1e12)
解题思路:
这道题就是题意有点不好懂,, 懂了之后还是挺好写的, BFS可以求出到达每个点的时间, 对于叶子节点单独存起来。 之后的每个询问都可以二分去查找。
代码:
//2017-08-07 10:25
//2017-08-07 11:02
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int MaxN = 1e5;
int n, m, seq[MaxN + 5], cnt, tot, T;
int all, pre[2 * MaxN + 5], last[MaxN + 5], other[2 * MaxN + 5];
LL ans[MaxN + 5], cost[2 * MaxN + 5], t[MaxN + 5];
bool vis[MaxN + 5];
struct Node {
LL s; int v;
}p[MaxN + 5];
bool cmp(Node a, Node b){ return a.s < b.s; }
void build(int u, int v, LL w){
pre[++all] = last[u];
last[u] = all;
other[all] = v;
cost[all] = w;
}
void Bfs(){
memset(vis, 0, sizeof(vis));
int head = 1, tial = 0;
seq[++tial] = 1, vis[1] = true, t[1] = 0;
while(head <= tial){
int now = seq[head];
int ed = last[now];
tot = 0;
while(ed != -1){
int dr = other[ed];
if(!vis[dr]){
vis[dr] = true;
seq[++tial] = dr;
p[++tot].v = dr;
p[tot].s = cost[ed];
}
ed = pre[ed];
}
if(tot == 0) ans[++cnt] = t[now];
else{
sort(p + 1, p + 1 + tot, cmp);
t[p[1].v] = t[now] + p[1].s;
for(int i= 2; i <= tot; i++)
t[p[i].v] = t[now] + p[1].s + (p[i].s - p[1].s) * 2;
}
head++;
}
}
int main(){
scanf("%d", &T);
while(T--){
all = -1, memset(last, -1, sizeof(last));
scanf("%d", &n);
for(int i = 2; i <= n; i++){
int u; LL w;
scanf("%d %lld", &u, &w);
build(i, u, w);
build(u, i, w);
}
cnt = 0;
Bfs();
sort(ans + 1, ans + 1 + cnt);
scanf("%d", &m);
while(m--){
LL x;
scanf("%lld", &x);
int l = 1, r = cnt, res = 0, mid;
while(l <= r){
mid = (l + r) >> 1;
if(ans[mid] <= x) res = mid, l = mid + 1;
else r = mid - 1;
}
printf("%d\n", res);
}
}
return 0;
}