大概就是二分+树上差分...

题意:给你树上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 运输计划相关推荐

  1. 洛谷P2680 运输计划(倍增LCA + 树上差分 + 二分答案)

    [题目链接] [思路]: 根据题意可以明显看出,当所有任务都完成时的时间是最终的结果,也就是说本题要求,求出最小的最大值. 那这样的话就暗示了将答案二分,进行check. [check方法]: 如果说 ...

  2. 洛谷P2680:运输计划(倍增、二分、树上差分)

    传送门 文章目录 题目描述 解析 问题 代码 题目描述 解析 求最大值的最小值 容易想到二分 然后...就没有然后了... 看了题解 学会了一个新技能:树上差分 (其实学长之前好像讲过...) 一般的 ...

  3. 洛谷 2680 运输计划 题解

    博客观赏效果更佳 题意简述 n n n个点的边带权树,给 m m m条关键的链.把树上一条边的权值变为0,使得 m m m条链的和中,最大值最小. n , m < = 1 e 5 n,m< ...

  4. 洛谷 P1137 旅行计划 题解

    洛谷 P1137 旅行计划 题解 洛谷 P1137 题目 小明要去一个国家旅游.这个国家有 N N N个城市,编号为1至 N N N,并且有 M M M条道路连接着,小明准备从其中一个城市出发,并只往 ...

  5. 洛谷 P1137 旅行计划 1

    题目描述 小明要去一个国家旅游.这个国家有N个城市,编号为1-N,并且有M条道路连接着,小明准备从其中一个城市出发,并只往东走到城市i停止. 所以他就需要选择最先到达的城市,并制定一条路线以城市i为终 ...

  6. 2021寒假——洛谷刷题计划(35题)

    (希望大家不要Copy) AC:Accept,程序通过. CE:Compile Error,编译错误. PC:Partially Correct,部分正确. WA:Wrong Answer,答案错误. ...

  7. P2680 运输计划(树上差分+lca+二分)

    题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间 ...

  8. P2680 运输计划

    传送门 十分显然完成工作的时间和航耗时最长的运输计划有关 所以题目意思就是要求最大值最小 所以可以想到二分 把所有大于mid时间的航线打上标记,显然删边只能在所有这些航线的公共路径上 要如何快速打标记 ...

  9. luogu P2680 运输计划 (二分答案+树上差分)

    题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间 ...

  10. 题解——洛谷 P2680 NOIP提高组 2015 运输计划

    树上差分加上二分答案 详细题解待填坑 #include <cstdio> #include <algorithm> #include <cstring> using ...

最新文章

  1. 理解 IntelliJ IDEA 的项目配置和Web部署
  2. legnano里的看板成员及权限规则?项目成员及规则?
  3. R包库安装及数据加载:一次安装多个R包、一次加载多个R包
  4. Lucene核心数据结构——FST存词典,跳表存倒排或者roarning bitmap 见另外一个文章...
  5. jexus防止产生 *.core文件
  6. linux命令scp
  7. 运维人员应该掌握哪些常用技术
  8. C# 连接SQLServer数据库及登录验证知识
  9. Invalid bound statement (not found): com.xxxx.dao.other.LoginDao.getUser
  10. awk 内嵌正则 提取字符串_使用awk提取字符串中的数字或字母
  11. Camtasia实用技巧之智能聚焦
  12. 韩顺平 java 坦克大战_Tankgame 韩顺平版本的坦克大战,详细包括源代码,素材以及对应文件 Java Develop 263万源代码下载- www.pudn.com...
  13. Java中的JDK动态代理
  14. 事故赔付额年降高达7成,所托瑞安打造商用车智能驾驶商业化样本
  15. 2010年会考计算机试题,2010年浙江省信息技术会考试题 选择题 - 多媒体 - 图文
  16. Excel程序员常用快捷键
  17. ideal拉代码和提交代码
  18. 如何将chrome浏览器的默认语言改成中文呢?
  19. 记录一次teamview无法远程连接对方teamview的过程
  20. cb4cle计数器如何设计九分频电路

热门文章

  1. 解决ubuntu系统使用vim时方向键乱跳问题
  2. Relay和Rendezvous
  3. 网易2016在线笔试小结
  4. 计算机图形学-五角星的画法(转)
  5. 如何让OpenwrtX86和win7双系统共存在一块硬盘
  6. strongswan源代码结构与数据结构
  7. 关于模拟信号和数字信号的储存
  8. swift野梦抄袭 taylor_断眉质疑Taylor Swift新歌抄袭《Next to Me》,双方粉丝掀起骂战...
  9. itunes无法安装到win7系统更新服务器失败怎么办啊,Win7系统安装iTunes失败出错无法安装的解决方法...
  10. ipad为什么显示itunes store无法连接服务器,ipad无法连接itunes store怎么办