首页 > 其他分享 >P2680 [NOIP2015 提高组] 运输计划 (树上差分-边差分)

P2680 [NOIP2015 提高组] 运输计划 (树上差分-边差分)

时间:2022-10-06 11:47:52浏览次数:103  
标签:NOIP2015 return int P2680 差分 mid fa maxn cnt

P2680

题目的大意就是走完m条路径所需要的最短时间(边权是时间), 其中我们可以把一条边的权值变成0(也就是题目所说的虫洞)。

可以考虑二分答案x,找到一条边,使得所有大于x的路径经过这条边(差分维护),并且路径减去这条边的边权后小等于x,通过这样判定x是否可行。

 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N = 3e5 + 10;
 5 int tot, head[N], to[N << 1], nxt[N << 1], edge[N << 1];
 6 int n, m, fa[N][25], dep[N], dis[N], pre[N], num[N];
 7 struct node {
 8     int x, y, lca;
 9 }q[N];
10 void add(int x, int y, int z) {
11     nxt[++ tot] = head[x], head[x] = tot, to[tot] = y, edge[tot] = z;
12 }
13 void dfs(int u, int f) {
14     dep[u] = dep[f] + 1;
15     fa[u][0] = f;  
16     for (int i = 1; i <= 20; i ++) 
17         fa[u][i] = fa[fa[u][i - 1]][i - 1];
18     for (int i = head[u]; i; i = nxt[i]) {
19         int v = to[i];
20         if (v == f) continue;
21         pre[v] = edge[i];//v所在这条边的边权 
22         dis[v] = dis[u] + edge[i];
23         dfs(v, u); 
24     }
25 }
26 int getlca(int x, int y) {
27     if (dep[x] < dep[y]) swap(x, y);
28     for (int i = 20; i >= 0; i --) {
29         if (dep[fa[x][i]] >= dep[y]) x = fa[x][i];
30     }
31     if (x == y) return x;
32     for (int i = 20; i >= 0; i --) {
33         if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
34     }
35     return fa[x][0];
36 }
37 int flag, cnt, maxn;
38 int judge(int u, int f, int cnt, int maxn) {//返回子树和 
39     int k = num[u];
40     for (int i = head[u]; i; i = nxt[i]) {
41         int v = to[i];
42         if (v == f) continue;
43         k += judge(v, u, cnt, maxn);
44     }
45     if (k >= cnt && pre[u] >= maxn) flag = 1;
46     //所有>mid的边都经过u所在这条边i,且i的权值满足条件 
47     return k;
48 }
49 bool check(ll mid) {
50     memset(num, 0, sizeof num);
51     maxn = cnt = flag = 0;
52     for (int i = 1; i <= m; i ++) {
53         int d = dis[q[i].x] + dis[q[i].y] - 2 * dis[q[i].lca];
54         if (d > mid) {
55             num[q[i].x] ++, num[q[i].y] ++, num[q[i].lca] -= 2;
56             cnt ++;
57             maxn = max(maxn, d);
58         }
59     }
60     if (!cnt) return 1; // !!!!!
61     judge(1, 0, cnt, maxn - mid);
62     return flag;
63 }
64 int main() {
65     scanf("%d %d", &n, &m);
66     for (int i = 1; i < n; i ++) {
67         int a, b, c;
68         scanf("%d %d %d", &a, &b, &c);
69         add(a, b, c), add(b, a, c);
70     }
71     dfs(1, 0);
72     for (int i = 1; i <= m; i ++) {
73         scanf("%d %d", &q[i].x, &q[i].y);
74         q[i].lca = getlca(q[i].x, q[i].y);    
75     }
76     ll l = 0, r = 300000000;
77     while (l < r) {
78         ll mid = (l + r) >> 1;
79         if (check(mid)) r = mid;
80         else l = mid + 1;
81     }
82     printf("%lld\n", l);
83     return 0;
84 } 

 

标签:NOIP2015,return,int,P2680,差分,mid,fa,maxn,cnt
From: https://www.cnblogs.com/YHxo/p/16757289.html

相关文章

  • 贤鱼的刷题日常--P2671 [NOIP2015 普及组] 求和
    ......
  • 差分与二维差分
    一、基础差分1.问题:多次区间修改,一次单点查询2.思路:对于区间问题,我们可以使用前缀和与线段树。线段树过于复杂,我们可以从前缀和来思考。考虑到每一次单点修改,前缀和都是......
  • P2671 [NOIP2015 普及组] 求和(洛谷前缀和
    P2671[NOIP2015普及组]求和1//(x+z)*(num[x]+num[z])=2//(x1+x2)*(y1+y2)+(x1+x3)*(y1+y3)+(x2+x3)*(y2+y3)3//=x1*(y1*(n-2)+y1+y2+...+yn)4//+x2*(y2*......
  • 考察交互的方差分析与简单效应分析(附带操作数据)
    1.案例背景与分析策略1.1案例背景介绍治疗缺铁性贫血病人12例,分4组给予基础疗法和甲乙两种药物治疗,一个月后观察红细胞增加数(百万/mm),试分析甲乙用药对治疗效果的影响。......
  • 如何做方差分析?
    方差分析是在20世纪年代发展起来的一种统计方法,它是由英国统计学家费希尔在进行试验设计时为解释试验数据而首先引入的,根据所分析的自变量多少,方差分析一般包括单因素方差......
  • 差分数组
    数据量不大时频繁的区间修改问题设d为差分数组对区间[l,r]加x,则d[l]+=x,d[r+1]-=x那么原数组中,第i个数的值为d从0到i的前缀和证明:为什么时0到i的前缀和呢?因......
  • 差分约束笔记
    一个差分约束系统,是由多个形如\(x_i-x_j\leqc\)的不等式组成的。现在,我们要试图找出一组解,使得这些不等式都能被满足。我们在求最短路的过程中,用到一个和上面很像的式......
  • 通关基本算法 day_06 -- 差分
    差分原理差分是前缀和的逆运算给定一个长度为n的a数组,构造一个b数组,使得:$$a_i=b_1+b_2+b_3+...+b_i\b_1=a_1\b_2=a_2-a_1\b_n=a_n-a_{n-1}$$b就称为a的......
  • 【学习笔记】差分约束系统
    【图论】差分约束系统前置芝士SPFA判负环与最短路SPFA判负环负环定义:边の权值之和为负数的环不会真的有人不会SPFA吧先放张图就是在SPFA跑最短路的时候判断一下有......
  • 前缀和与差分
    前缀和一维前缀和前缀和数组d[i]=d[i-1]+a[i];前缀和公式sum=a[r]-a[l-1];模版#include<bits/stdc++.h>#include<algorithm>usingnamespacestd;intn,m,a[10......