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

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

链接:https://www.luogu.org/problemnew/show/P4149

题目描述

给一棵树,每条边有权。求一条简单路径,权值和等于 KK ,且边的数量最小。

输入输出格式

输入格式:

 

第一行:两个整数 n,kn,k 。

第二至 nn 行:每行三个整数,表示一条无向边的两端和权值 (注意点的编号从 00 开始)。

 

输出格式:

 

一个整数,表示最小边数量。

如果不存在这样的路径,输出 -11 。

 

输入输出样例

输入样例#1: 
4 30 1 11 2 21 3 4
输出样例#1: 
2

说明

n200000,K1000000 。

 

题解:点分, 统计经过中心长度为k且边数最少的路径,对每条路径记录属于哪棵子树,一个子树不能合并,不合法;

注意统计时的左右端点,zjj同学帮我调试了好久

还有,洛谷上不开O2要RE?

// luogu-judger-enable-o2#include
#include
#include
using namespace std;const int M = 200005, K = 1000001;struct ST{
int dis, id, les;}tong[M];bool cmp(ST a, ST b){ return a.dis < b.dis;}int n, tot, cnt, Ans = M, k, root, sum, h[M], siz[M], dis[M], f[M], dep[M];bool vis[M];struct edge{
int v, nxt, w;}G[M<<1];void add(int u, int v, int w){ G[++tot].v = v; G[tot].w = w; G[tot].nxt = h[u]; h[u] = tot;}void init(){ memset(vis, 0, sizeof(vis)); memset(h, 0, sizeof(h)); tot = 0; Ans = K; sum = 0;}void getroot(int u, int fa){ siz[u] = 1; f[u] = 0; for(int i = h[u]; i; i = G[i].nxt){ int v = G[i].v; if(vis[v] || v == fa)continue; getroot(v, u); siz[u] += siz[v]; f[u] = max(f[u], siz[v]); } f[u] = max(f[u], sum - siz[u]); if(f[u] < f[root]) root = u; }void getdeep(int u, int fa, int zx){ tong[++cnt].dis = dis[u]; tong[cnt].id = zx; tong[cnt].les = dep[u]; for(int i = h[u]; i; i = G[i].nxt){ int v = G[i].v; if(vis[v] || v == fa)continue; dis[v] = dis[u] + G[i].w; dep[v] = dep[u] + 1; if(zx == -1)zx = u; getdeep(v, u, zx); }}void cal(int u, int ret){ dis[u] = ret; dep[u] = 0; cnt = 0; tong[++cnt].dis = dis[u]; tong[cnt].id = u; tong[cnt].les = 0; for(int i = h[u]; i; i = G[i].nxt){ int v = G[i].v; if(vis[v])continue; dis[v] = dis[u] + G[i].w; dep[v] = dep[u] + 1; getdeep(v, u, v); } sort(tong+1, tong+1+cnt, cmp); int lf = 1, rg = cnt; while(lf < rg){ while(tong[lf].dis + tong[rg].dis < k && lf <= cnt)lf++; while(tong[lf].dis + tong[rg].dis > k && rg >= 1)rg--; if(lf >= cnt || rg <= 1 || lf >= rg)break; int llf = lf, rrg = rg; if(tong[lf].dis + tong[rg].dis == k){ while(tong[llf].dis == tong[lf].dis && llf <= cnt)llf++; while(tong[rrg].dis == tong[rg].dis && rrg >= 1)rrg--; for(int i = lf; i < llf; i++) for(int j = rrg+1; j <= rg; j++) if(tong[i].id != tong[j].id) Ans = min(Ans, tong[i].les + tong[j].les); lf = llf, rg = rrg; } } }void solve (int u){ cal(u, 0); vis[u] = 1; for(int i = h[u]; i; i = G[i].nxt){ int v = G[i].v; if(vis[v])continue; sum = siz[v]; getroot(v, root = 0); solve(root); }}int main(){ f[0] = 1e9; scanf("%d%d", &n, &k); for(int i = 1; i < n; i++){ int u, v, w; scanf("%d%d%d", &u, &v, &w); add(u + 1, v + 1, w); add(v + 1, u + 1, w); } sum = n; getroot(1, 0); solve(root); if(Ans == M)printf("-1\n"); else printf("%d\n", Ans);}
View Code

 

 

这几天没调出一道程序,都是zjj同学帮我的,怎么感觉代码水平越学越烂?

2018-08-15 

转载于:https://www.cnblogs.com/EdSheeran/p/9483260.html

你可能感兴趣的文章
MySQL合并多行
查看>>
[openstack] RDO Quickstart
查看>>
[转载]struts2 中的 addActionError 、addFieldEr
查看>>
[转载]我的PMP复习备考经验谈(上篇)—— 一本关于PMP备考的小指南
查看>>
Mysql命令集
查看>>
记java应用linux服务单个CPU使用率100%分析
查看>>
将文件字节输出流写入到文本中
查看>>
Linux编程之给你的程序开后门
查看>>
Ubuntu下Hadoop的安装和配置
查看>>
VS2010中生成遇到的 web.config 问题
查看>>
Nginx安装部署(反向代理与负载均衡)
查看>>
2018年最新小程序一键智能生成平台限时限量销售!
查看>>
集合遍历过程iterator, 添加删除元素报异常
查看>>
echarts一些笔记
查看>>
最长上升子序列
查看>>
Java-面向对象
查看>>
salesforce 零基础学习(四十四)实现checkbox列表简单过滤功能
查看>>
Android 异步下载
查看>>
c# 中 利用 CookieContainer 对 Cookie 进行序列化和反序列化校验
查看>>
Leetcode 743. Closest Leaf in a Binary Tree
查看>>