[IOI 2011]Race
Description
给一棵树,每条边有非负权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, 1 <= 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
题解
做了一上午的狗屎题,其实很水(点分裸题)...老是找不出细节错误....
- 在每一棵点分治的树中只考虑经过根的路径;
- (1)某一点到根的路径
- 只需要算出每个点到根的距离即可判断。
- (2)来自根节点不同儿子所在子树的两个点构成的路径
- 每个点相当于有三个参数$belong[i]$,$dis[i]$,$s[i]$,分别表示删除根后属于哪个联通快,到根的路径长度以及路径上的边数;
- 原问题相当于求$min(s[i]+s[j])$,$belong[i]!=belong[j]$,$dis[i]+dis[j]=k$。
- (1)某一点到根的路径
- 依次处理根的每一棵子树;
- $f[i]$表示已经处理过的子树中到根距离为$i$的点中$s$值最小为多少;
- 当处理下一棵子树时,每个点所能匹配的点到根的距离都是固定的,直接拿出对应的$f$值更新答案即可,然后利用这棵子树更新$f$数组;
- 这样保证了更新答案的两点$belong$值不同,$dis$相加等于$k$,同时直接找出当前最优解。
- 易发现,所有路径都是在这个方法中考虑过的,显然是可行的。
//It is made by Awson on 2017.9.20
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <string>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define LL long long
using namespace std;
const int N = ;
const int K = ;
const int INF = ~0u>>; inline int Read() {
int sum = ;
char ch = getchar();
while (ch < '' || ch > '') ch = getchar();
while (ch >= '' && ch <= '') sum = (sum<<) + (sum<<) + ch - , ch = getchar();
return sum;
}
int n, k, u, v, c;
struct tt {
int to, cost, next;
}edge[N*+];
int path[N+], top;
int ans = INF;
int size[N+], mxsize[N+];
bool vis[N+];
int minsize, root;
int f[K+]; inline void add(int u, int v, int c) {
edge[++top].to = v;
edge[top].cost = c;
edge[top].next = path[u];
path[u] = top;
}
void dfs_size(int u, int fa) {
size[u] = ;
mxsize[u] = ;
for (int i = path[u]; i; i = edge[i].next)
if ((!vis[edge[i].to]) && edge[i].to != fa) {
dfs_size(edge[i].to, u);
size[u] += size[edge[i].to];
mxsize[u] = Max(mxsize[u], size[edge[i].to]);
}
}
void dfs_getroot(int r, int u, int fa) {
mxsize[u] = Max(mxsize[u], size[r]-size[u]);
if (mxsize[u] < minsize) minsize = mxsize[u], root = u;
for (int i = path[u]; i; i = edge[i].next)
if ((!vis[edge[i].to]) && edge[i].to != fa)
dfs_getroot(r, edge[i].to, u);
}
void dfs_getans(int u, int fa, int cnt, int val) {
if (val > k) return;
if (val == k) {
ans = Min(ans, cnt);
return;
}
int tmp = k-val;
if (f[tmp]) ans = Min(f[tmp]+cnt, ans);
for (int i = path[u]; i; i = edge[i].next)
if ((!vis[edge[i].to]) && edge[i].to != fa)
dfs_getans(edge[i].to, u, cnt+, val+edge[i].cost);
}
void dfs_update(int u, int fa, int cnt, int val) {
if (val >= k) return;
if (!f[val]) f[val] = cnt;
else f[val] = Min(f[val], cnt);
for (int i = path[u]; i; i = edge[i].next)
if ((!vis[edge[i].to]) && edge[i].to != fa)
dfs_update(edge[i].to, u, cnt+, val+edge[i].cost);
}
void dfs_delete(int u, int fa, int val) {
if (val >= k) return;
f[val] = ;
for (int i = path[u]; i; i = edge[i].next)
if ((!vis[edge[i].to]) && edge[i].to != fa)
dfs_delete(edge[i].to, u, val+edge[i].cost);
}
void solve(int x) {
minsize = INF;
dfs_size(x, );
dfs_getroot(x, x, );
vis[root] = true;
for (int i = path[root]; i; i = edge[i].next)
if (!vis[edge[i].to]) {
dfs_getans(edge[i].to, root, , edge[i].cost);
dfs_update(edge[i].to, root, , edge[i].cost);
}
for (int i = path[root]; i; i = edge[i].next)
if (!vis[edge[i].to])
dfs_delete(edge[i].to, root, edge[i].cost);
for (int i = path[root]; i; i = edge[i].next)
if (!vis[edge[i].to])
solve(edge[i].to);
}
void work() {
for (int i = ; i < n; i++) {
u = Read(); v = Read(); c = Read();
u++, v++;
add(u, v, c);
add(v, u, c);
}
ans = INF;
solve();
printf("%d\n", ans == INF ? - : ans);
}
int main() {
int size = << ; //==========//
char *p = (char*)malloc(size) + size; //手 动 扩 栈//
__asm__("movl %0, %%esp\n" :: "r"(p)); //==========//
n = Read(); k = Read();
work();return ;
}
[IOI 2011]Race的更多相关文章
- 洛谷 P4149 [ IOI 2011 ] Race —— 点分治
题目:https://www.luogu.org/problemnew/show/P4149 仍然是点分治: 不过因为是取 min ,所以不能用容斥,那么子树之间就必须分开算,记录桶时注意这个: 每次 ...
- 【BZOJ 2599】【IOI 2011】Race 点分治
裸的点分治,然而我因为循环赋值$s$时把$i <= k$写成$i <= n$了,WA了好长时间 #include<cstdio> #include<cstring> ...
- 【IOI 2011】Race
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2599 [算法] 点分治 [代码] #include<bits/stdc++.h ...
- [IOI 2011]ricehub
Description 乡间有一条笔直而长的路称为“米道”.沿着这条米道上 R 块稻田,每块稻田的坐标均为一个 1 到 L 之间(含 1 和 L)的整数.这些稻田按照坐标以不减的顺序给出,即对于 0 ...
- 【题解】Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths Codeforces 741D DSU on Tree
Prelude 很好的模板题. 传送到Codeforces:(* ̄3 ̄)╭ Solution 首先要会DSU on Tree,不会的看这里:(❤ ω ❤). 众所周知DSU on Tree是可以用来处 ...
- 【BZOJ-2599】Race 点分治
2599: [IOI2011]Race Time Limit: 70 Sec Memory Limit: 128 MBSubmit: 2590 Solved: 769[Submit][Status ...
- hdu 4123 Bob’s Race 树的直径+rmq+尺取
Bob’s Race Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Probl ...
- USACO Section 4.3 Street Race(图的连通性+枚举)
虽说是IOI'95,但是也是挺水的..for 第一问,n最大为50,所以可以直接枚举起点和终点之外的所有点,然后dfs判断是否连通:for 第二问,易知答案一定是第一问的子集,所以从第一问中的答案中枚 ...
- POJ 4003 Bob’s Race && HDU4123 Bob’s Race (dfs+rmq)
Bob’s Race Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 378 Accepted: 119 Descript ...
随机推荐
- 【R语言系列】R语言初识及安装
一.R是什么 R语言是由新西兰奥克兰大学的Ross Ihaka和Robert Gentleman两个人共同发明. 其词法和语法分别源自Schema和S语言. R定义:一个能够自由幼小的用于统计计算和绘 ...
- django之urls系统
Django的urls系统简介 Django 1.11版本 URLConf官方文档 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映 ...
- 连接数据后,当执行查询语句报错:ORA-01219: 数据库未打开: 仅允许在固定表/视图中查询
参考博客:http://blog.csdn.net/lanchengxiaoxiao/article/details/40982771 1.在cmd窗口通过sqlplus连接数据库 C:\Users\ ...
- c语音-第零次作业
1.你认为大学的学习生活.同学关系.师生应该是怎样? 我认为大学学习应该以自我学习为主,由以往的被动学习改为主动学习,探索新世界,除学习专业知识外对自身欠缺的地方也应该加以补足:同学之间要互相帮助,更 ...
- Software Engineering-HW1
title: Software Engineering-HW1 date: 2017-09-13 15:41:13 tags: HW --- 阅读随笔 在<徐宥:掉进读书的兔子洞>里面, ...
- Beta阶段总结分析报告
1 讨论照片 2 Postmortem结果 二手交易平台项目Postmortem结果 整理:程环宇 设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有 ...
- JAVA_SE基础——64.StringBuffer类 ①
字符串特点:字符串是常量:它们的值在创建之后不能更改 字符串的内容一旦发生了变化,那么马上会创建一个新的对象. 注意:字符串的内容不适宜频繁修改,因为一旦修改马上就会创建一个新的对象. publ ...
- C语言Linix服务器网络爬虫项目(二)项目设计和通过一个http请求抓取网页的简单实现
我们通过上一篇了解了爬虫具体要实现的工作之后,我们分析得出的网络爬虫的基本工作流程如下: 1.首先选取一部分精心挑选的种子URL: 2.将这些URL放入待抓取URL队列: 3.从待抓取URL队列中取出 ...
- 在bootstrap中让竖向排列的输入框水平排列
在bootstrap中可以使用自带的样式标记来控制样式,但是同时可以利用最原始的css样式来解决达到需求 如下所示可以看出来两个inline-block就可以使得两个水平排列 block和inline ...
- ASP.NET CORE 自定义视图组件(ViewComponent)注意事项
*红色字体为固定命名,蓝色为一般命名规则,黄色为ASP.NET CORE 默认查找文件名 概要:1.简单ViewComponent的用法 2.ViewComponent控制器返回值 3.注意事项 1 ...