• 【UOJ #150】【NOIP 2015】运输计划


    http://uoj.ac/problem/150

    用树链剖分求lca,二分答案树上差分判断。

    时间复杂度$O(nlogn)$,n,m同阶。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 300003;
    int in() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = (k << 3) + (k << 1) + c - '0';
    	return k * fh;
    }
    
    struct QQ {int u, v, lca, len;} Q[N];
    struct node {int nxt, to, w;} E[N << 1];
    int n, m, cnt = 0, point[N], size[N], son[N], top[N], deep[N], fa[N];
    int DFN[N], tot = 0, dis[N], fa_dis[N];
    
    void ins(int u, int v, int w) {
    	E[++cnt] = (node) {point[u], v, w}; point[u] = cnt;
    }
    
    void _(int x) {
    	size[x] = 1; DFN[++tot] = x;
    	for(int i = point[x]; i; i = E[i].nxt)
    		if (E[i].to != fa[x]) {
    			fa[E[i].to] = x;
    			deep[E[i].to] = deep[x] + 1;
    			dis[E[i].to] = dis[x] + E[i].w;
    			fa_dis[E[i].to] = E[i].w;
    			_(E[i].to);
    			size[x] += size[E[i].to];
    			if (size[E[i].to] > size[son[x]])
    				son[x] = E[i].to;
    		}
    }
    
    void __(int x) {
    	if (!son[x]) return;
    	top[son[x]] = top[x];
    	__(son[x]);
    	for(int i = point[x]; i; i = E[i].nxt)
    		if (E[i].to != son[x] && E[i].to != fa[x])
    			{top[E[i].to] = E[i].to; __(E[i].to);}
    }
    
    int LCA(int u, int v) {
    	while (top[u] != top[v]) {
    		if (deep[top[u]] < deep[top[v]]) swap(u, v);
    		u = fa[top[u]];
    	}
    	return deep[u] < deep[v] ? u : v;
    }
    
    int del[N], cont, maxnow;
    
    bool check(int s) {
    	cont = 0; maxnow = 0;
    	memset(del, 0, sizeof(int) * (n + 1));
    	for(int i = 1; i <= m; ++i)
    		if (Q[i].len > s) {
    			++del[Q[i].u];
    			++del[Q[i].v];
    			del[Q[i].lca] -= 2;
    			++cont;
    			maxnow = max(maxnow, Q[i].len - s);
    		}
    	
    	if (!cont) return true;
    	for(int i = n; i > 1; --i) del[fa[DFN[i]]] += del[DFN[i]];
    	for(int i = 2; i <= n; ++i)
    		if (fa_dis[i] >= maxnow && del[i] == cont)
    			return true;
    	return false;
    }
    
    int main() {
    	n = in(); m = in();
    	int u, v, w;
    	for(int i = 1; i < n; ++i) {
    		u = in(); v = in(); w = in();
    		ins(u, v, w);
    		ins(v, u, w);
    	}
    	
    	_(1);
    	top[1] = 1; __(1);
    	
    	int left = 0, right = 0, mid;
    	for(int i = 1; i <= m; ++i) {
    		Q[i].u = in(); Q[i].v = in();
    		Q[i].lca = LCA(Q[i].u, Q[i].v);
    		Q[i].len = dis[Q[i].u] + dis[Q[i].v] - (dis[Q[i].lca] << 1);
    		right = max(right, Q[i].len);
    	}
    	
    	while (left < right) {
    		mid = (left + right) >> 1;
    		if (check(mid)) right = mid;
    		else left = mid + 1;
    	}
    	
    	printf("%d
    ", left);
    	return 0;
    }
    

    QwQ

  • 相关阅读:
    css透明度的兼容!!!
    csshtml布局及部分知识小分享~~~
    js面向对象选项卡
    JQ弹出框移动-插件分享~~~
    nginx配置phpcms v9伪静态规则 phpcms伪静态 404 Not Found
    mysql数据库常见优化方法
    帝国ECMS静态生成为一行代码/静态页面打乱教程
    帝国cms 批量删除或者清空classurl(二级域名绑定)
    jquery实现一个网页同时调用多个倒计时
    PHPCMSV9 单文件上传功能代码
  • 原文地址:https://www.cnblogs.com/abclzr/p/5800230.html
Copyright © 2020-2023  润新知