洛谷P2680 运输计划
大概就是二分+树上差分...
题意:给你树上m条路径,你要把一条边权变为0,使最长的路径最短。
最大的最小,看出二分(事实上我并没有看出来...)
然后二分k,对于所有大于k的边,树上差分求出最长公共边,然后看是否可以。
(yy的解法②:边按照长度排序,然后二分。删除最长公共边。据logeadd juru说是三分)
代码量3.6k,180行,还是有点长的。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 const int N = 300010; 5 6 inline void read(int &x) { 7 char c = getchar(); 8 x = 0; 9 while(c > '9' || c < '0') { 10 c = getchar(); 11 } 12 while(c <= '9' && c >= '0') { 13 x = (x << 3) + (x << 1) + c - 48; 14 c = getchar(); 15 } 16 return; 17 } 18 19 struct Edge { 20 int v, nex, len; 21 }edge[N << 1]; int top; 22 23 int e[N], n, m, lm, fa[N][20], d[N], lenth[N]; /// 点 24 int l[N], r[N], mid[N], len[N]; /// 路径 25 bool use[N]; /// 树上差分 26 int num, large, R, f[N]; 27 28 inline void add(int x, int y, int z) { 29 edge[++top].v = y; 30 edge[top].len = z; 31 edge[top].nex = e[x]; 32 e[x] = top; 33 return; 34 } 35 36 inline void DFS1(int x, int f) { 37 fa[x][0] = f; 38 for(int i = e[x]; i; i = edge[i].nex) { 39 int y = edge[i].v; 40 if(y != f) { 41 lenth[y] = lenth[x] + edge[i].len; 42 d[y] = d[x] + 1; 43 DFS1(y, x); 44 } 45 } 46 return; 47 } 48 49 inline void getlca() { 50 while((1 << lm) < n) { 51 lm++; 52 } 53 DFS1(1, 0); 54 for(int i = 1; i <= lm; i++) { 55 for(int x = 1; x <= n; x++) { 56 fa[x][i] = fa[fa[x][i - 1]][i - 1]; 57 } 58 } 59 return; 60 } 61 62 inline int lca(int x, int y) { 63 if(d[x] > d[y]) { 64 std::swap(x, y); 65 } 66 int t = lm; 67 while(t > -1 && d[y] > d[x]) { 68 if(d[fa[y][t]] >= d[x]) { 69 y = fa[y][t]; 70 } 71 t--; 72 } 73 if(x == y) { 74 return x; 75 } 76 t = lm; 77 while(t > -1 && fa[x][0] != fa[y][0]) { 78 if(fa[x][t] != fa[y][t]) { 79 x = fa[x][t]; 80 y = fa[y][t]; 81 } 82 t--; 83 } 84 return fa[x][0]; 85 } 86 87 inline int DFS(int x) { 88 int cnt = 0; 89 for(int i = e[x]; i; i = edge[i].nex) { 90 int y = edge[i].v; 91 if(y == fa[x][0]) { 92 continue; 93 } 94 int temp = DFS(y); 95 cnt += temp; 96 if(temp == num) { 97 large = std::max(large, edge[i].len); 98 } 99 } 100 cnt += f[x]; 101 return cnt; 102 } 103 104 inline bool check(int k) { 105 num = 0; 106 memset(f, 0, sizeof(f)); 107 for(int i = 1; i <= m; i++) { 108 bool t = len[i] > k; 109 use[i] = t; 110 num += t; 111 if(t) { 112 f[l[i]]++; 113 f[r[i]]++; 114 f[mid[i]] -= 2; 115 } 116 } 117 large = 0; 118 DFS(1); 119 return R - large <= k; 120 } 121 122 inline int getlong(int i) { 123 int x = l[i]; 124 int ans = 0; 125 while(x != mid[i]) { 126 ans = std::max(ans, lenth[x] - lenth[fa[x][0]]); 127 x = fa[x][0]; 128 } 129 x = r[i]; 130 while(x != mid[i]) { 131 ans = std::max(ans, lenth[x] - lenth[fa[x][0]]); 132 x = fa[x][0]; 133 } 134 return ans; 135 } 136 137 int main() { 138 scanf("%d%d", &n, &m); 139 int x, y, z; 140 for(int i = 1; i < n; i++) { 141 //scanf("%d%d%d", &x, &y, &z); 142 read(x); 143 read(y); 144 read(z); 145 add(x, y, z); 146 add(y, x, z); 147 } 148 getlca(); 149 int dr = 0, dl = 0, dm, A = 1; 150 for(int i = 1; i <= m; i++) { 151 //scanf("%d%d", &l[i], &r[i]); 152 read(l[i]); 153 read(r[i]); 154 mid[i] = lca(l[i], r[i]); 155 len[i] = lenth[l[i]] + lenth[r[i]] - 2 * lenth[mid[i]]; 156 if(len[i] > dr) { 157 dr = len[i]; 158 A = i; 159 } 160 } 161 R = dr; 162 dl = dr - getlong(A); 163 if(dl < 0) { 164 printf("ERROR "); 165 } 166 while(dl < dr) { 167 dm = (dr + dl) / 2; 168 if(check(dm)) { 169 //printf("check %d 1 \n", dm); 170 dr = dm; 171 } 172 else { 173 //printf("check %d 0 \n", dm); 174 dl = dm + 1; 175 } 176 } 177 printf("%d", dr); 178 return 0; 179 }
AC代码
转载于:https://www.cnblogs.com/huyufeifei/p/9622962.html
洛谷P2680 运输计划相关推荐
- 洛谷P2680 运输计划(倍增LCA + 树上差分 + 二分答案)
[题目链接] [思路]: 根据题意可以明显看出,当所有任务都完成时的时间是最终的结果,也就是说本题要求,求出最小的最大值. 那这样的话就暗示了将答案二分,进行check. [check方法]: 如果说 ...
- 洛谷P2680:运输计划(倍增、二分、树上差分)
传送门 文章目录 题目描述 解析 问题 代码 题目描述 解析 求最大值的最小值 容易想到二分 然后...就没有然后了... 看了题解 学会了一个新技能:树上差分 (其实学长之前好像讲过...) 一般的 ...
- 洛谷 2680 运输计划 题解
博客观赏效果更佳 题意简述 n n n个点的边带权树,给 m m m条关键的链.把树上一条边的权值变为0,使得 m m m条链的和中,最大值最小. n , m < = 1 e 5 n,m< ...
- 洛谷 P1137 旅行计划 题解
洛谷 P1137 旅行计划 题解 洛谷 P1137 题目 小明要去一个国家旅游.这个国家有 N N N个城市,编号为1至 N N N,并且有 M M M条道路连接着,小明准备从其中一个城市出发,并只往 ...
- 洛谷 P1137 旅行计划 1
题目描述 小明要去一个国家旅游.这个国家有N个城市,编号为1-N,并且有M条道路连接着,小明准备从其中一个城市出发,并只往东走到城市i停止. 所以他就需要选择最先到达的城市,并制定一条路线以城市i为终 ...
- 2021寒假——洛谷刷题计划(35题)
(希望大家不要Copy) AC:Accept,程序通过. CE:Compile Error,编译错误. PC:Partially Correct,部分正确. WA:Wrong Answer,答案错误. ...
- P2680 运输计划(树上差分+lca+二分)
题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间 ...
- P2680 运输计划
传送门 十分显然完成工作的时间和航耗时最长的运输计划有关 所以题目意思就是要求最大值最小 所以可以想到二分 把所有大于mid时间的航线打上标记,显然删边只能在所有这些航线的公共路径上 要如何快速打标记 ...
- luogu P2680 运输计划 (二分答案+树上差分)
题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间 ...
- 题解——洛谷 P2680 NOIP提高组 2015 运输计划
树上差分加上二分答案 详细题解待填坑 #include <cstdio> #include <algorithm> #include <cstring> using ...
最新文章
- 理解 IntelliJ IDEA 的项目配置和Web部署
- legnano里的看板成员及权限规则?项目成员及规则?
- R包库安装及数据加载:一次安装多个R包、一次加载多个R包
- Lucene核心数据结构——FST存词典,跳表存倒排或者roarning bitmap 见另外一个文章...
- jexus防止产生 *.core文件
- linux命令scp
- 运维人员应该掌握哪些常用技术
- C# 连接SQLServer数据库及登录验证知识
- Invalid bound statement (not found): com.xxxx.dao.other.LoginDao.getUser
- awk 内嵌正则 提取字符串_使用awk提取字符串中的数字或字母
- Camtasia实用技巧之智能聚焦
- 韩顺平 java 坦克大战_Tankgame 韩顺平版本的坦克大战,详细包括源代码,素材以及对应文件 Java Develop 263万源代码下载- www.pudn.com...
- Java中的JDK动态代理
- 事故赔付额年降高达7成,所托瑞安打造商用车智能驾驶商业化样本
- 2010年会考计算机试题,2010年浙江省信息技术会考试题 选择题 - 多媒体 - 图文
- Excel程序员常用快捷键
- ideal拉代码和提交代码
- 如何将chrome浏览器的默认语言改成中文呢?
- 记录一次teamview无法远程连接对方teamview的过程
- cb4cle计数器如何设计九分频电路
热门文章
- 解决ubuntu系统使用vim时方向键乱跳问题
- Relay和Rendezvous
- 网易2016在线笔试小结
- 计算机图形学-五角星的画法(转)
- 如何让OpenwrtX86和win7双系统共存在一块硬盘
- strongswan源代码结构与数据结构
- 关于模拟信号和数字信号的储存
- swift野梦抄袭 taylor_断眉质疑Taylor Swift新歌抄袭《Next to Me》,双方粉丝掀起骂战...
- itunes无法安装到win7系统更新服务器失败怎么办啊,Win7系统安装iTunes失败出错无法安装的解决方法...
- ipad为什么显示itunes store无法连接服务器,ipad无法连接itunes store怎么办