博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj2599 [IOI2011]Race
阅读量:5341 次
发布时间:2019-06-15

本文共 3130 字,大约阅读时间需要 10 分钟。

2599: [IOI2011]Race

Time Limit: 70 Sec  Memory Limit: 128 MB
Submit: 4559  Solved: 1343
[][][]

Description

给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000

Input

第一行 两个整数 n, k

第二..n行 每行三个整数 表示一条无向边的两端和权值 (注意点的编号从0开始)

Output

一个整数 表示最小边数量 如果不存在这样的路径 输出-1

Sample Input

4 3
0 1 1
1 2 2
1 3 4

Sample Output

2

HINT

 2018.1.3新加数据一组,未重测

分析:复习了一下点分治. 这道题在点分治模板的基础上改改就好了. dfs到一个点添加重心到它的距离和经过的边数,最后两个指针扫一下就好了.

#include 
#include
#include
#include
#include
using namespace std;const int maxn = 300010;int n,k,head[maxn],to[maxn * 2],nextt[maxn * 2],w[maxn * 2],tot = 1,d[maxn],num[maxn];int sizee[maxn],f[maxn],sum,root,vis[maxn],ans[1000010],anss = -1,top;struct node{ int p1,p2;}e[maxn];void add(int x,int y,int z){ w[tot] = z; to[tot] = y; nextt[tot] = head[x]; head[x] = tot++;}void findroot(int u,int fa){ sizee[u] = 1; f[u] = 0; for (int i = head[u]; i; i = nextt[i]) { int v = to[i]; if (vis[v] || v == fa) continue; findroot(v,u); sizee[u] += sizee[v]; f[u] = max(f[u],sizee[v]); } f[u] = max(f[u],sum - sizee[u]); if (f[u] < f[root]) root = u;}void dfs1(int u,int d1,int d2,int fa){ d[u] = d1; num[u] = d2; for (int i = head[u];i;i = nextt[i]) { int v = to[i]; if (vis[v] || v == fa) continue; dfs1(v,d1 + w[i],d2 + 1,u); }}void dfs2(int u,int fa){ e[++top].p1 = d[u]; e[top].p2 = num[u]; for (int i = head[u];i;i = nextt[i]) { int v = to[i]; if (vis[v] || v == fa) continue; dfs2(v,u); }}bool cmp(node a,node b){ if (a.p1 == b.p1) return a.p2 < b.p2; return a.p1 < b.p1;}void calc1(int u,int W){ top = 0; dfs2(u,0); sort(e + 1,e + 1 + top,cmp); int l = 1,r = top; while (l <= r) { while (l < r && e[l].p1 + e[r].p1 > k) r--; for (int kk = r; e[l].p1 + e[kk].p1 == k; kk--) //这里不是直接移动r. ans[e[kk].p2 + e[l].p2]++; l++; }}void calc2(int u,int W){ top = 0; dfs2(u,0); sort(e + 1,e + 1 + top,cmp); int l = 1,r = top; while (l <= r) { while (l < r && e[l].p1 + e[r].p1 > k) r--; for (int kk = r; e[l].p1 + e[kk].p1 == k; kk--) ans[e[kk].p2 + e[l].p2]--; l++; }}void solve(int u){ vis[u] = 1; dfs1(u,0,0,0); calc1(u,0); for (int i = head[u]; i; i = nextt[i]) { int v = to[i]; if (vis[v]) continue; calc2(v,w[i]); f[0] = sum = sizee[v]; findroot(v,root = 0); solve(root); }}int main(){ scanf("%d%d",&n,&k); for (int i = 1; i < n; i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); x++; y++; add(x,y,z); add(y,x,z); } f[0] = sum = n; findroot(1,0); solve(root); for (int i = 1; i <= n; i++) if (ans[i]) { anss = i; break; } printf("%d\n",anss); return 0;}

 

转载于:https://www.cnblogs.com/zbtrs/p/8509167.html

你可能感兴趣的文章
12个大调都是什么
查看>>
angular、jquery、vue 的区别与联系
查看>>
参数范围的选择
查看>>
使用 MarkDown & DocFX 升级 Rafy 帮助文档
查看>>
THUPC2019/CTS2019/APIO2019游记
查看>>
Nodejs Express模块server.address().address为::
查看>>
4.3.5 Sticks (POJ1011)
查看>>
POJ 2960 S-Nim 博弈论 sg函数
查看>>
Dijkstra模版
查看>>
一个简单的插件式后台任务管理程序
查看>>
GDB调试多进程程序
查看>>
组合数
查看>>
第二章作业心得
查看>>
CMD批处理延时启动的几个方法
查看>>
转:LoadRunner中web_custom_request 和 web_submit_data的差别
查看>>
HTC G7直刷MIUI开启A2SD+亲测教程
查看>>
shiro的rememberMe不生效
查看>>
const 不兼容的类型限定符问题
查看>>
OpenCV的配置
查看>>
spring Cache + Redis 开发数据字典以及自定义标签
查看>>