P4149 [IOI2011]Race
对于这道题,明显是点分治,权值等于k,可以用桶统计树上路径(但注意要清空);
对于每颗子树,先与之前的子树拼k,再更新桶,维护t["len"]最小边数;
#include <bits/stdc++.h>
using namespace std;
#define up(i,l,r) for(register int i = (l); i <= (r); ++i)
#define dn(i,l,r) for(register int i = (l); i >= (r); --i)
#define ll long long
#define re register
using namespace std;
template <typename T> void in(T &x) {
x = ; T f = ; char ch = getchar();
while(!isdigit(ch)) {if(ch == '-') f = -; ch = getchar();}
while( isdigit(ch)) {x = * x + ch - ; ch = getchar();}
x *= f;
}
template <typename T> void out(T x) {
if(x < ) x = -x , putchar('-');
if(x > ) out(x/);
putchar(x% + );
}
//---------------------------------------------------------
const int N = 2e5+,inf = 1e9+;
int n,k; struct edge {
int v,w,nxt;
}e[N<<]; int tot,head[N]; void add(int u,int v,int w) {
e[++tot].v = v; e[tot].w = w,e[tot].nxt = head[u]; head[u] = tot;
} int Tsize,rt;
int f[N],size[N];
int dis[N],dep[N]; int t[]; bool vis[N];
int ans = inf; void get_rt(int u,int fa) {
size[u] = ; f[u] = ;
for(int i = head[u]; i ;i = e[i].nxt) {
int v = e[i].v; if(v == fa || vis[v]) continue;
get_rt(v,u); size[u] += size[v];
//if(f[u] < size[v]) f[u] = size[v];
f[u] = max(f[u],size[v]);
}
f[u] = max(f[u],Tsize-size[u]);
if(f[u] < f[rt]) rt = u;
} void get_ans(int u,int fa) {
//if(dis[u] > k) return;//>
if(dis[u] <= k)
ans = min(ans,t[k-dis[u]]+dep[u]);
for(int i = head[u]; i;i = e[i].nxt) {
int v = e[i].v; if(v == fa || vis[v]) continue;
dis[v] = dis[u] + e[i].w; dep[v] = dep[u] + ;
get_ans(v,u); //!!!!!未写
}
} void update_t(int u,int fa,bool flag) {
//if(dis[u] > k) return;//>
if(dis[u] <= k) {
if(flag) t[dis[u]] = min(t[dis[u]],dep[u]);
else t[dis[u]] = inf;
}
for(int i = head[u]; i ;i = e[i].nxt) {
int v = e[i].v; if(v == fa || vis[v]) continue;
update_t(v,u,flag);
}
} void solve(int u) {
vis[u] = ; t[] = ; //dep[u] = 0;
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].v; if(vis[v]) continue;
dep[v] = ,dis[v] = e[i].w; get_ans(v,); update_t(v,,);
}
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].v; if(vis[v]) continue;
update_t(v,,);
}
for(int i = head[u]; i ; i = e[i].nxt) {
int v = e[i].v; if(vis[v]) continue;
Tsize = size[v],rt = ; get_rt(v,); solve(rt);
//rt - > v
}
} int main() {
in(n); in(k); int x,y,w;
up(i,,n-) in(x),in(y),in(w),add(x+,y+,w),add(y+,x+,w);
up(i,,k) t[i] = inf;
Tsize = n,rt = ,f[] = n+; get_rt(,); solve(rt);
if(ans != inf) out(ans); else out(-);
return ;
}
P4149 [IOI2011]Race的更多相关文章
- 模板—点分治B(合并子树)(洛谷P4149 [IOI2011]Race)
洛谷P4149 [IOI2011]Race 点分治作用(目前只知道这个): 求一棵树上满足条件的节点二元组(u,v)个数,比较典型的是求dis(u,v)(dis表示距离)满足条件的(u,v)个数. 算 ...
- 洛谷P4149 [IOI2011]Race(点分治)
题目描述 给一棵树,每条边有权.求一条简单路径,权值和等于 KK ,且边的数量最小. 输入输出格式 输入格式: 第一行:两个整数 n,kn,k . 第二至 nn 行:每行三个整数,表示一条无向边的 ...
- [洛谷P4149][IOI2011]Race
题目大意:给一棵树,每条边有边权.求一条简单路径,权值和等于$K$,且边的数量最小. 题解:点分治,考虑到这是最小值,不满足可减性,于是点分中的更新答案的地方计算重复的部分要做更改,就用一个数组记录前 ...
- P4149 [IOI2011]Race 点分治
思路: 点分治 提交:5次 题解: 刚开始用排序+双指针写的,但是调了一晚上,总是有两个点过不了,第二天发现原因是排序时的\(cmp\)函数写错了:如果对于路径长度相同的,我们从小往大按边数排序,当双 ...
- LUOGU P4149 [IOI2011]Race
题目描述 给一棵树,每条边有权.求一条简单路径,权值和等于 KKK ,且边的数量最小. 输入输出格式 输入格式: 第一行:两个整数 n,kn,kn,k . 第二至 nnn 行:每行三个整数,表示一条无 ...
- 洛谷$P4149\ [IOI2011]\ Race$ 点分治
正解:点分治 解题报告: 传送门$QwQ$ 昂先不考虑关于那个长度的限制考虑怎么做? 就开个桶,记录所有边的取值,每次加入边的时候查下是否可行就成$QwQ$ 然后现在考虑加入这个长度的限制?就考虑把这 ...
- 洛谷 P4149 [IOI2011]Race-树分治(点分治,不容斥版)+读入挂-树上求一条路径,权值和等于 K,且边的数量最小
P4149 [IOI2011]Race 题目描述 给一棵树,每条边有权.求一条简单路径,权值和等于 KK,且边的数量最小. 输入格式 第一行包含两个整数 n, Kn,K. 接下来 n - 1n−1 行 ...
- BZOJ 2599: [IOI2011]Race( 点分治 )
数据范围是N:20w, K100w. 点分治, 我们只需考虑经过当前树根的方案. K最大只有100w, 直接开个数组CNT[x]表示与当前树根距离为x的最少边数, 然后就可以对根的子树依次dfs并更新 ...
- [IOI2011]Race
2599: [IOI2011]Race Time Limit: 70 Sec Memory Limit: 128 MBhttp://www.lydsy.com/JudgeOnline/problem ...
随机推荐
- V-REP Remote API(C++)实现简单的关节转动
基础内容参考:https://www.cnblogs.com/eternalmoonbeam/p/10753149.html V-REP客户端设置: 在V-REP场景文件中需要添加三个实体,包括两个形 ...
- Why Everyone Should Lift Weights
Why Everyone Should Lift Weights by James Clear I'll say it plain and simple: you should be lifting ...
- windows中,VS2017下,在Cmake中添加OpenCV依赖
OpenCV_DIR -----D:/OpenCV/3.3.0/opencv/build/x64/vc14/lib 只有这个目录 cmake才认..貌似是因为找到了对应的OpenCvConfig.c ...
- [Tools] 一种调试 Android App 接口的方式 (Fiddler/Wireshark)
要求:Windows电脑与手机在同一局域网内(Wifi). [ Fiddler 设置代理 ] 下载地址:https://www.telerik.com/download/fiddler 依次 Tool ...
- JavaScript Array some() 方法
some 判断数组中是否至少有一个元素满足条件 只要有一个满足就返回true 只有都不满足时才返回false 语法: array.some(function(value,index,array),th ...
- FileProvider的使用及应用更新时提示:解析包出错、失败等问题
Android 7.0以上的版本更新采用系统自带的DownloadManager更新 DOWNLOADPATH ="/download/" https://www.jianshu. ...
- 安装软件,遇到弹框Windows Installer Coordinator,一直循环卡在这个弹框处
转载自https://www.cliftonsystems.co.uk/fixing-windows-installer-coordinator-loop/ 复制粘贴原文内容,以防将来访问不到原网页了 ...
- Linux下使用ps命令查看某个进程文件的启动位置
ps -ef|grep shutdown ls -al /proc/4170
- Oracle主从同步、双向同步的配置
(本教程展示了Windows环境的oracle数据库主从同步,Linux环境一样也可以) (把主数据库obpm 和从数据库orcl 用实际的数据库名给替换掉) (配置主从同步后,再配置双向同步,可能会 ...
- L2-028 秀恩爱分得快(模拟)
古人云:秀恩爱,分得快. 互联网上每天都有大量人发布大量照片,我们通过分析这些照片,可以分析人与人之间的亲密度.如果一张照片上出现了 K 个人,这些人两两间的亲密度就被定义为 1/K.任意两个人如果同 ...