洛谷 P5021 [NOIP2018]赛道重建
洛谷 P5021 [NOIP2018]赛道重建
传送门
思路
思路就是常规的思路,所以就不说了……我就是来记录一下我的\(AC\)之路的,真的是太爽了

没错……我也是一个个打的部分分,最后终于AC的,至于为什么中间又会有\(35\)、\(25\)、\(0\)这样的分数……纯粹是因为我犯了zz错误……
代码
1、\(b_i = a_i + 1\) 链的情况
#include <bits/stdc++.h>
using namespace std;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
return x * f;
}
const int N = 50011;
int a[N], n, m, cnt, head[N], sum;
struct node {
int to, nxt, val;
} e[N << 1];
inline void add(int from, int to, int w) {
e[++cnt].to = to;
e[cnt].val = w;
e[cnt].nxt = head[from];
head[from] = cnt;
}
void dfs(int x, int fa) {
for(int i = head[x]; i ; i = e[i].nxt) {
int y = e[i].to;
if(y == fa) continue;
dfs(y, x);
a[x] = e[i].val;
}
}
int check(int k) {
int t = 0, now = 1;
for(int i = 1; i < n; i++) {
if(now + a[i] >= k) {
now = 0;
t++;
}
else now += a[i];
}
return t >= m;
}
int main() {
n = read(), m = read();
for(int i = 1; i < n; i++) {
int u = read(), v = read(), w = read();
add(u, v, w);
add(v, u, w);
sum += w;
}
dfs(1, 0);
int l = 1, r = sum, mid;
while(l < r) {
mid = (l + r) >> 1;
if(check(mid)) l = mid;
else r = mid - 1;
}
cout << l << '\n';
}
2、\(m = 1\) 求树的直径
#include <bits/stdc++.h>
using namespace std;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
return x * f;
}
const int N = 50011;
int a[N], n, m, cnt, head[N], sum, ans;
struct node {
int to, nxt, val;
} e[N << 1];
inline void add(int from, int to, int w) {
e[++cnt].to = to;
e[cnt].val = w;
e[cnt].nxt = head[from];
head[from] = cnt;
}
int dfs(int x,int fa) {
int sum1 = 0, sum2 = 0;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fa) continue;
sum2 = max(sum2, dfs(y, x) + e[i].val);
if(sum2 > sum1) swap(sum1, sum2);
}
ans = max(ans, sum1 + sum2);
return sum1;
}
int main() {
n = read(), m = read();
for(int i = 1; i < n; i++) {
int u = read(), v = read(), w = read();
add(u, v, w);
add(v, u, w);
sum += w;
}
dfs(1, 0);
cout << ans << '\n';
}
3、\(a_i = 1\) 菊花图
#include <bits/stdc++.h>
using namespace std;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
return x * f;
}
const int N = 50011;
const int inf = 0x3f3f3f3f;
int a[N], n, m, cnt, head[N], sum, ans;
struct node {
int to, nxt, val;
} e[N << 1];
inline void add(int from, int to, int w) {
e[++cnt].to = to;
e[cnt].val = w;
e[cnt].nxt = head[from];
head[from] = cnt;
}
bool cmp(int a, int b) {
return a > b;
}
int main() {
n = read(), m = read();
for(int i = 1; i < n; i++) {
int u = read(), v = read(), w = read();
add(u, v, w);
add(v, u, w);
sum += w;
}
for(int i = head[1], y; i; i = e[i].nxt) {
y = e[i].to;
a[y - 1] = e[i].val;
}
sort(a + 1, a + n, cmp);
int ans = inf;
for(int i = 1; i <= m; i++)
ans = min(ans, a[i] + a[2 * m - i + 1]);
cout << ans << '\n';
return 0;
}
4、混起来的部分分
#include <bits/stdc++.h>
using namespace std;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
return x * f;
}
const int N = 50011;
const int inf = 0x3f3f3f3f;
int a[N], n, m, cnt, head[N], sum, ans;
struct node {
int to, nxt, val;
} e[N << 1];
inline void add(int from, int to, int w) {
e[++cnt].to = to;
e[cnt].val = w;
e[cnt].nxt = head[from];
head[from] = cnt;
}
namespace subtask1 {
int a[N];
void dfs(int x, int fa) {
for(int i = head[x]; i ; i = e[i].nxt) {
int y = e[i].to;
if(y == fa) continue;
dfs(y, x);
a[x] = e[i].val;
}
}
int check(int k) {
int t = 0, now = 1;
for(int i = 1; i < n; i++) {
if(now + a[i] >= k) {
now = 0;
t++;
} else now += a[i];
}
return t >= m;
}
void solve() {
dfs(1, 0);
int l = 1, r = sum, mid;
while(l < r) {
mid = (l + r + 1) >> 1;
if(check(mid)) l = mid;
else r = mid - 1;
}
cout << l << '\n';
}
}
namespace subtask2 {
int dfs(int x,int fa) {
int sum1 = 0, sum2 = 0;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fa) continue;
sum2 = max(sum2, dfs(y, x) + e[i].val);
if(sum2 > sum1) swap(sum1, sum2);
}
ans = max(ans, sum1 + sum2);
return sum1;
}
void solve() {
dfs(1, 0);
cout << ans << '\n';
}
}
namespace subtask3 {
bool cmp(int a, int b) {
return a > b;
}
void solve() {
for(int i = head[1], y; i; i = e[i].nxt) {
y = e[i].to;
a[y - 1] = e[i].val;
}
sort(a + 1, a + n, cmp);
int ans = inf;
for(int i = 1; i <= m; i++)
ans = min(ans, a[i] + a[2 * m - i + 1]);
cout << ans << '\n';
}
}
int main() {
n = read(), m = read();
int flag = 1, f = 1;
for(int i = 1; i < n; i++) {
int u = read(), v = read(), w = read();
add(u, v, w);
add(v, u, w);
if(u != 1) flag = 0;
if(v != u + 1) f = 0;
sum += w;
}
if(flag) {
subtask3::solve();
}
else if(f){
subtask1::solve();
}
else {
subtask2::solve();
}
return 0;
}
5、正解!!(\(multiset\))
#include <bits/stdc++.h>
using namespace std;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
return x * f;
}
const int N = 50011;
const int inf = 0x3f3f3f3f;
int a[N], n, m, cnt, head[N], ans, up;
struct node {
int to, nxt, val;
} e[N << 1];
multiset<int> s[N];
multiset<int>::iterator it;
inline void add(int from, int to, int w) {
e[++cnt].to = to;
e[cnt].val = w;
e[cnt].nxt = head[from];
head[from] = cnt;
}
int dfs(int x, int fa, int k) {
s[x].clear();
int w;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fa) continue;
w = dfs(y, x, k) + e[i].val;
if(w >= k) ans++;
else s[x].insert(w);
}
int maxn = 0;
while(!s[x].empty()) {
if(s[x].size() == 1) {
return max(maxn, *s[x].begin());
}
it = s[x].lower_bound(k - *s[x].begin());
if(it == s[x].begin() && s[x].count(*it) == 1) it++;
if(it == s[x].end()) {
maxn = max(maxn, *s[x].begin());
s[x].erase(s[x].find(*s[x].begin()));
} else {
ans++;
s[x].erase(s[x].find(*it));
s[x].erase(s[x].find(*s[x].begin()));
}
}
return maxn;
}
int dfs1(int x,int fa) {
int sum1 = 0, sum2 = 0;
for(int i = head[x], y; i; i = e[i].nxt) {
y=e[i].to;
if(y == fa) continue;
sum2 = max(sum2, dfs1(y, x) + e[i].val);
if(sum1 < sum2) swap(sum1, sum2);
}
up = max(up, sum1 + sum2);
return sum1;
}
int check(int k) {
ans = 0;
dfs(1, 0, k);
if(ans >= m) return 1;
return 0;
}
int main() {
n = read(), m = read();
for(int i = 1; i < n; i++) {
int u = read(), v = read(), w = read();
add(u, v, w);
add(v, u, w);
}
dfs1(1, 0);
int l = 1, r = up, mid;
while(l < r) {
mid = (l + r + 1) >> 1;
if(check(mid)) l = mid;
else r = mid - 1;
}
cout << l << '\n';
}
洛谷 P5021 [NOIP2018]赛道重建的更多相关文章
- 洛谷P5021 赛道修建 NOIp2018 贪心+二分答案
正解:贪心+LCA+二分答案 解题报告: 想先港下部分分qwq因为我部分分只拿到了10ptsQAQ(时间不够不是理由,其实还是太弱,所以要想很久,所以才时间不够QAQ m=1 找直径长度,完 一条链 ...
- 洛谷P5021 赛道修建
题目 首先考虑二分,然后发现最小长度越大的话,赛道就越少.所以可以用最终的赛道个数来判断长度是否合理.问题转化为给定一个长度,问最多有多少条互不重叠路径比这个给定长度大. 考虑贪心,毕竟贪心也是二分c ...
- 洛谷P1119 灾后重建[Floyd]
题目背景 B地区在地震过后,所有村庄都造成了一定的损毁,而这场地震却没对公路造成什么影响.但是在村庄重建好之前,所有与未重建完成的村庄的公路均无法通车.换句话说,只有连接着两个重建完成的村庄的公路才能 ...
- 洛谷——P1119 灾后重建
P1119 灾后重建 题目背景 B地区在地震过后,所有村庄都造成了一定的损毁,而这场地震却没对公路造成什么影响.但是在村庄重建好之前,所有与未重建完成的村庄的公路均无法通车.换句话说,只有连接着两个重 ...
- 洛谷 P4198 楼房重建 线段树维护单调栈
P4198 楼房重建 题目链接 https://www.luogu.org/problemnew/show/P4198 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上 ...
- 洛谷 P1119 灾后重建——dijstra
先上一波题目 https://www.luogu.org/problem/P1119 这道题我们可以将询问按时间排序 然后随着询问将相应已经重建成功的点进行操作 每次更新一个点就以他为起点跑一遍dij ...
- 洛谷 P1119 灾后重建 最短路+Floyd算法
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例 输出样例 说明 思路 AC代码 总结 题面 题目链接 P1119 灾后重建 题目描述 B地区在地震过后,所有村 ...
- 洛谷 [P1119] 灾后重建
我们发现每次询问都是对于任意两点的,所以这是一道多源最短路径的题,多源最短路径,我们首先想到floyd,因为询问的时间是不降的,所以对于每次询问,我们将还没有进行松弛操作的的点k操作. #includ ...
- 洛谷P1119灾后重建
题目 做一个替我们首先要明确一下数据范围,n<=200,说明n^3的算法是可以过得,而且这个题很明显是一个图论题, 所以我们很容易想到这个题可以用folyd, 但是我在做这个题的时候因为没有深刻 ...
随机推荐
- python-10-列表、元组嵌套
前言 元组.列表前面章节有讲解实例,本节内容是列表.元组的多嵌套. 一.列表嵌套 1.列表嵌套操作1 # 列表的嵌套 li = ['xiaolong', '小林', ['小龙', 'xiaol'], ...
- R语言填充空缺值
在R语言中, imputeMissings包的特点是,如果空值是数值型,则使用median代替,如果使用的是character类型,则使用mode值代替. imputeMissing中,需要的包是im ...
- java、JavaScript获取微信用户信息登录优化方案
1.获取微信用户信息要调用微信的好几个接口,再加上自己系统的接口就会变的很慢,影响用户体验,之前走过的弯路我就不赘述了,直接说新的方案. 2.第一步都是向微信发起获取用户code请求: 请求接口:ht ...
- scrapy学习笔记(二)框架结构工作原理
scrapy结构图: scrapy组件: ENGINE:引擎,框架的核心,其它所有组件在其控制下协同工作. SCHEDULER:调度器,负责对SPIDER提交的下载请求进行调度. DOWNLOADER ...
- Java开发设计——UML类图
Java开发设计——UML类图 摘要:本文主要介绍了UML类图的相关知识. 简介 在UML中,类使用包含类名.属性和操作且带有分隔线的长方形来表示,类图分为三层. 第一层是类的名称,如果是抽象类或接口 ...
- Python【day 12】生成器和推导式
一.生成器和生成器函数1.生成器和生成器函数的概念 1.生成器的本质是迭代器 2.函数中包含yield,就是生成器函数 2.生成器函数的写法 def func(): a =10 yield 20 ge ...
- reduce求和真方便
1.reduce的用法. reduce是JavaScript中的一个方法,常用于数组求和,接收两个参数,第一个参数为累加函数,第二个参数为初始值,这个初始值是前面那个累加函数的参数.如果不指定初始值, ...
- 010.[转] maven的三大生命周期
一.Maven的生命周期 Maven的生命周期就是对所有的构建过程进行抽象和统一.包含了项目的清理.初始化.编译.测试.打包.集成测试.验证.部署和站点生成等几乎所有的构建步骤. Maven的生命周期 ...
- django更换ORM连接处理(连接池)转
1 概述 在使用 Django 进行 Web 开发时, 我们避免不了与数据库打交道. 当并发量低的时候, 不会有任何问题. 但一旦并发量达到一定数量, 就会导致 数据库的连接数会被瞬时占满. 这将导致 ...
- requests---session简介
http协议是无状态的,也就是每个请求都是独立的.那么登录后的一系列动作,都需要用cookie来验证身份是否是登录状态,为了高效的管理会话,保持会话,于是就有了session session简介 se ...