【BZOJ2599】[IOI2011]Race 树的点分治
【BZOJ2599】[IOI2011]Race
Description
给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000
Input
第一行 两个整数 n, k
第二..n行 每行三个整数 表示一条无向边的两端和权值 (注意点的编号从0开始)
Output
一个整数 表示最小边数量 如果不存在这样的路径 输出-1
Sample Input
0 1 1
1 2 2
1 3 4
Sample Output
题解:本题大部分代码都与POJ1741那道模板题相同,只不过是calc函数里有些不一样
如果我们想计算一棵子树里的答案,仍然是先按照每个点到根的距离排序,然后用双指针法算出长度=m的路径,那么问题来了,我们怎样将答案中的非简单路径去掉呢?
由于我们最终要求的是经过边最少的长度=m的简单路径,那么我们可以用ans[i]保存经过i条边的路径数,然后在calc的时候直接修改ans就行了
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=200010;
int to[maxn<<1],next[maxn<<1],val[maxn<<1],dep[maxn],s[maxn],head[maxn],siz[maxn];
int vis[maxn],ans[maxn],p[maxn];
int n,m,tot,cnt,root,maxx; bool cmp(int a,int b)
{
return s[a]<s[b];
}
void add(int a,int b,int c)
{
to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
}
void getroot(int x,int fa)
{
int i,mx=0;
siz[x]=1;
for(i=head[x];i!=-1;i=next[i])
{
if(to[i]==fa||vis[to[i]]) continue;
getroot(to[i],x);
siz[x]+=siz[to[i]];
mx=max(mx,siz[to[i]]);
}
mx=max(mx,tot-siz[x]);
if(maxx>mx) root=x,maxx=mx;
}
void getdep(int x,int fa)
{
p[++p[0]]=x;
for(int i=head[x];i!=-1;i=next[i])
{
if(to[i]==fa||vis[to[i]]) continue;
s[to[i]]=s[x]+val[i],dep[to[i]]=dep[x]+1;
getdep(to[i],x);
}
}
void calc(int x,int flag)
{
p[0]=0,getdep(x,0);
sort(p+1,p+p[0]+1,cmp);
int l=1,r=p[0],i;
for(;l<r;l++)
{
while(l<r&&s[p[l]]+s[p[r]]>m) r--;
for(i=r;i>l&&s[p[l]]+s[p[i]]==m;i--) ans[dep[p[l]]+dep[p[i]]]+=flag;
}
}
void dfs(int x)
{
vis[x]=1;
s[x]=dep[x]=0,calc(x,1);
for(int i=head[x];i!=-1;i=next[i])
{
if(vis[to[i]]) continue;
s[to[i]]=val[i],dep[to[i]]=1,calc(to[i],-1);
maxx=1<<30,tot=siz[to[i]],getroot(to[i],x);
dfs(root);
}
}
int main()
{
scanf("%d%d",&n,&m);
int i,a,b,c;
memset(head,-1,sizeof(head));
for(i=1;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c),a++,b++;
add(a,b,c),add(b,a,c);
}
maxx=1<<30;
getroot(1,0);
dfs(1);
for(i=1;i<=n;i++)
{
if(ans[i])
{
printf("%d\n",i);
return 0;
}
}
printf("-1");
return 0;
}
【BZOJ2599】[IOI2011]Race 树的点分治的更多相关文章
- [bzoj2599][IOI2011]Race——点分治
Brief Description 给定一棵带权树,你需要找到一个点对,他们之间的距离为k,且路径中间的边的个数最少. Algorithm Analyse 我们考虑点分治. 对于子树,我们递归处理,所 ...
- [luogu4149][bzoj2599][IOI2011]Race【点分治】
题目描述 给一棵树,每条边有权.求一条简单路径,权值和等于 K,且边的数量最小. 题解 比较明显需要用到点分治,我们定义\(d\)数组表示当前节点到根节点\(rt\)之间有多少个节点,也可以表示有多少 ...
- 2019.01.09 bzoj2599: [IOI2011]Race(点分治)
传送门 题意:给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小. 思路: 考虑点分治如何合并. 我们利用树形dpdpdp求树的直径的方法,边dfsdfsdfs子树边统计答案即可. 代码: ...
- BZOJ2599 [IOI2011]Race 【点分治】
题目 给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000 输入格式 第一行 两个整数 n, k 第二..n行 每行三个整 ...
- bzoj2599: [IOI2011]Race(点分治)
写了四五道点分治的题目了,算是比较理解点分治是什么东西了吧= = 点分治主要用来解决点对之间的问题的,比如距离为不大于K的点有多少对. 这道题要求距离等于K的点对中连接两点的最小边数. 那么其实道理是 ...
- BZOJ2599:[IOI2011]Race(点分治)
Description 给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000 Input 第一行 两个整数 n, k 第二 ...
- 【点分治】【哈希表】bzoj2599 [IOI2011]Race
给nlog2n随便过的跪了,不得已弄了个哈希表伪装成nlogn(当然随便卡,好孩子不要学)…… 不过为啥哈希表的大小开小点就RE啊……?必须得超过数据范围一大截才行……谜 #include<cs ...
- bzoj1758 [Wc2010]重建计划 & bzoj2599 [IOI2011]Race
两题都是树分治. 1758这题可以二分答案avgvalue,因为avgvalue=Σv(e)/s,因此二分后只需要判断Σv(e)-s*avgvalue是否大于等于0,若大于等于0则调整二分下界,否则调 ...
- BZOJ2599——[IOI2011]Race
0.题意:给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小. 1.分析:水题一道,一波树分治就好 我们可以发现这个题的K是比较小的,才100w,那么我们可以树分治一下,在遍历每一棵子树的 ...
随机推荐
- 【转】java基本数据类型vs封装数据类型
1.基本概念 说java是面向对象的语言是正确的,但是她不纯,基本数据类型就不是对象. 基本数据类型可以大致分为三类:数据型:int.short.long.byte.float.double字符型:c ...
- Message Code 【27796】 Failed to connect to server 'hostname';port_ld': 'reason'.
Message Code [27796] Failed to connect to server 'hostname';port_ld': 'reason'.Unable to connect to ...
- RunnableException与CheckedException
Checked Exception 编译时异常 编译的时候检查你的代码可能在运行的时候抛出异常,这通常在编译的时候要去处理的. RunnableException 运行时异常,可以编译通过,但如果不处 ...
- 面向移动端的轻量级神经网络模型mobilenet、ShuffleNet
翻译: http://baijiahao.baidu.com/s?id=1565832713111936&wfr=spider&for=pc http://baijiahao.baid ...
- Intellij IDEA 使用学习
Intellij中名词解释: Project,就是一个完整的项目,类似Eclipse中的WorkSet(虽然WorkSet是人为归类的). Module,是Project中的模块,类似Eclipse中 ...
- 质量管理是SQA(软件质量保证)人员的职责
质量管理是SQA(软件质量保证)人员的职责
- 在C语言中实现面向对象(2)
C语言是结构化和模块化的语言,它是面向过程的.但它也可以模拟C++实现面向对象的功能.那么什么是对象呢?对象就是一个包含数据以及于这些数据有关的操作的集合,也就是包含数据成员和操作代码(即成员函数). ...
- php -- or 的用法
经常看到这样的语句: $file = fopen($filename, r) or die("抱歉,无法打开: $filename"); or 在这里是这样理解的,因为在PHP中并 ...
- erlang二进制的难理解的地方,有点神奇
40> <<A:16>> = <<1,2>>.<<1,2>>41> <<B:16/bits>> ...
- 如何使用GameObject类发送消息
一.GameObject发送消息的方法 GameObject类有三个方法可以实现发送消息,即SendMessage.BroadcastMessage和SendMessageUpwards.但是它们之间 ...