zoukankan      html  css  js  c++  java
  • 洛谷 P2680

    题目链接:P2680 运输计划

    题目大意

    题目要求的是我们找一条边,可以让这条边的权值变成0,然后给了你几对点,让你求在改变边的权值之后的最大值,然后输出最小的最大值

    solution

    最小值最大? 二分答案.

    那我们可以用LCA+树上差分来做(就这样不想写了)

    code:

    /**
    *    Author: Alieme
    *    Data: 2020.8.26
    *    Problem: Luogu P2680
    *    Time: O()
    */
    #include <cstdio>
    #include <iostream>
    #include <string>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    #define int long long
    #define rr register
    
    #define inf 1e9
    #define MAXN 1000010
    
    using namespace std;
    
    inline int read() {
    	int s = 0, f = 0;
    	char ch = getchar();
    	while (!isdigit(ch)) f |= ch == '-', ch = getchar();
    	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
    	return f ? -s : s;
    }
    
    void print(int x) {
    	if (x < 0) putchar('-'), x = -x;
    	if (x > 9) print(x / 10);
    	putchar(x % 10 + 48);
    }
    
    struct Node {
    	int u;
    	int v;
    	int lca;
    	int diss;
    }lu[MAXN];
    
    struct Edge {
    	int nxt;
    	int to;
    	int val;
    	Edge() {}
    	Edge(int Nxt, int To, int Val) {nxt = Nxt, to = To, val = Val;}
    }e[MAXN];
    
    int tot, n, m, cnt;
    
    int head[MAXN], dep[MAXN], dis[MAXN], temp[MAXN], num[MAXN];
    
    int fa[MAXN][30];
    
    inline void add(int from, int to, int val) {
    	e[++tot] = Edge(head[from], to, val);
    	head[from] = tot;
    }
    
    void dfs(int x, int fath) {
    	num[++cnt] = x;
    	dep[x] = dep[fath] + 1;
    	fa[x][0] = fath;
    	for (rr int i = 1; i < 25; i++)  fa[x][i] = fa[fa[x][i - 1]][i - 1];
    	for (rr int i = head[x]; i; i = e[i].nxt) {
    		int to = e[i].to;
    		if (to == fath) continue;
    		dis[to] = dis[x] + e[i].val;
    		dfs(to, x);
    	}
    }
    
    inline int LCA(int x, int y) {
    	if (dep[x] < dep[y]) swap(x, y);
    	int t = dep[x] - dep[y];
    	for (rr int i = 0; i < 25; i++)
    		if ((1 << i) & t)
    			x = fa[x][i];
    	if (x == y) return x;
    	for (rr int i = 24; i >= 0; i--) 
    		if (fa[x][i] != fa[y][i])
    			x = fa[x][i], y = fa[y][i];
    	return fa[x][0];
    }
    
    inline bool check(int x) {
    	int cnt = 0, ans = 0;
    	memset(temp, 0, sizeof temp);
    	for (rr int i = 1; i <= m; i++) 
    		if (lu[i].diss > x) {
    			temp[lu[i].u]++;
    			temp[lu[i].v]++;
    			temp[lu[i].lca] -= 2;
    			ans = max(ans, lu[i].diss - x);
    			cnt++;
    		}
    	if (cnt == 0) return true;
    	for (rr int i = n; i >= 1; i--) temp[fa[num[i]][0]] += temp[num[i]];
    	for (rr int i = 2; i <= n; i++) if (temp[i] == cnt && dis[i] - dis[fa[i][0]] >= ans) return true;
    	return false;
    }
    
    signed main() {
    	n = read();
    	m = read();
    	for (rr int i = 1; i < n; i++) {
    		int u = read();
    		int v = read();
    		int w = read();
    		add(u, v, w);
    		add(v, u, w);
    	}
    	dis[1] = 0;
    	dfs(1, 0);
    	for (rr int i = 1; i <= m; i++) {
    		lu[i].u = read();
    		lu[i].v = read();
    		lu[i].lca = LCA(lu[i].u, lu[i].v);
    		lu[i].diss = dis[lu[i].u] + dis[lu[i].v] - 2 * dis[lu[i].lca];
    	}
    	int l = 0, r = inf;
    	while (l < r) {
    		int mid = (l + r) >> 1;
    		if (check(mid)) r = mid;
    		else l = mid + 1;
    	}
    	print(l);
    }
    
  • 相关阅读:
    Web Service平台有三种元素构成:SOAP、WSDL、UDDI。区别和联系
    WSDL(Web服务描述语言)详细解析(全文转载学习用)
    SOAP和WebService的那些事
    成本加浮动酬金合同 成本加激励费用合同
    理解量子信息
    面向(过程、对象、组件、服务)编程
    POP-OOP-SOP-COP-SOA-AOP
    法律知识
    义帝熊心--秦末汉初
    接口绑定有几种实现方式,分别是怎么实现的?
  • 原文地址:https://www.cnblogs.com/lieberdq/p/13584312.html
Copyright © 2011-2022 走看看