zoukankan      html  css  js  c++  java
  • [CF1486F] Pairs of Paths

    Problem

    给定一棵树和若干个点对 ((u,v)) 给出的树上最短路径,求满足 路径交仅有一个点无序 路径对(即 ((a,b))((b,a)) 算一次)。

    Sol & Code

    交仅为一个点只有两种情况:两条路径 LCA 在同一个点或不在同一个点。

    分别计算。第一种使用容斥:交一个点、两个点、三个点加加减减;第二种较为简单,无需考虑交三个点的情况。注意要去掉两种情况之间的影响。复杂度 (mathcal O(nlog n))

    #include <bits/stdc++.h>
    using std::vector; using std::swap;
    typedef long long LL;
    const int N = 300005;
    int n, m;
    struct Edge { int v, nxt; } e[N * 2];
    int G[N * 2], edges = 0;
    void adde(int u, int v) {
    	e[edges++] = (Edge){v, G[u]}; G[u] = edges - 1;
    }
    int fa[19][N], dep[N];
    void dfs(int u, int f) {
    	dep[u] = dep[f] + 1; fa[0][u] = f;
    	for (int i = 1; i < 19; i++) fa[i][u] = fa[i - 1][fa[i - 1][u]];
    	for (int i = G[u]; ~i; i = e[i].nxt)
    		if (e[i].v != f) dfs(e[i].v, u);
    }
    void get(int &u, int d) {
    	for (int i = 0; d; i++, d >>= 1)
    		if (d & 1) u = fa[i][u];
    }
    int lca(int x, int y) {
    	if (dep[x] < dep[y]) swap(x, y);
    	get(x, dep[x] - dep[y]);
    	if (x == y) return x;
    	for (int i = 18; ~i; i--)
    		if (fa[i][x] != fa[i][y]) x = fa[i][x], y = fa[i][y];
    	return fa[0][x];
    }
    int sum[N], c[N]; LL ans = 0;
    struct node {
    	int x, y;
    	bool operator < (const node &o) const {
    		return x != o.x ? x < o.x : y < o.y;
    	}
    };
    vector<node> tg[N];
    void Dfs(int u) {
    	for (int i = G[u], v; ~i; i = e[i].nxt) 
    		if (v = e[i].v, v != fa[0][u])
    			Dfs(v), sum[u] += sum[v];
    	c[u] = sum[u] - tg[u].size();
    	sort(tg[u].begin(), tg[u].end());
    	ans += 1LL * tg[u].size() * c[u];
    	for (int i = 0; i < tg[u].size(); i++) {
    		if (tg[u][i].x) c[tg[u][i].x]--;
    		if (tg[u][i].y) c[tg[u][i].y]--;
    	}
    	for (int i = 0; i < tg[u].size(); i++) {
    		if (tg[u][i].x) ans -= c[tg[u][i].x];
    		if (tg[u][i].y) ans -= c[tg[u][i].y];
    	}
    	LL tot = 0;
    	for (int i = G[u], v; ~i; i = e[i].nxt)
    		if (v = e[i].v, v != fa[0][u]) c[v] = 0;
    	for (int i = 0; i < tg[u].size(); i++) {
    		if (tg[u][i].x) c[tg[u][i].x]++;
    		if (tg[u][i].y) c[tg[u][i].y]++;
    	}
    	tot += 1LL * tg[u].size() * tg[u].size();
    	for (int l = 0, r = 0; l < tg[u].size(); l = r) {
    		while (r < tg[u].size() && tg[u][l].x == tg[u][r].x && tg[u][l].y == tg[u][r].y) r++;
    		if (tg[u][l].x) tot -= 1LL * (r - l) * c[tg[u][l].x];
    		if (tg[u][l].y) tot -= 1LL * (r - l) * c[tg[u][l].y];
    		if (!tg[u][l].x || !tg[u][l].y) continue;
    		tot += 1LL * (r - l) * (r - l);
    	}
    	for (int i = 0; i < tg[u].size(); i++) {
    		if (tg[u][i].x || tg[u][i].y) break;
    		tot--;
    	}
    	ans += tot / 2;
    }
    int main() {
    	scanf("%d", &n);
    	memset(G, -1, sizeof G);
    	for (int i = 1; i < n; i++) {
    		int u, v; scanf("%d%d", &u, &v);
    		adde(u, v), adde(v, u);
    	}
    	dfs(1, 0);
    	scanf("%d", &m);
    	for (int i = 1; i <= m; i++) {
    		int u, v, t, x, y; scanf("%d%d", &u, &v); t = lca(u, v);
    		if (u == t) x = 0; else x = u, get(x, dep[u] - dep[t] - 1);
    		if (v == t) y = 0; else y = v, get(y, dep[v] - dep[t] - 1);
    		if (x > y) swap(x, y);
    		tg[t].push_back((node){x, y});
    		sum[u]++, sum[v]++, sum[t]--, sum[fa[0][t]]--;
    	}
    	Dfs(1);
    	printf("%lld", ans);
    	return 0;
    }
    
  • 相关阅读:
    laravel 单元测试 phpunit 运行报错 RuntimeException: No application encryption key has been specified 解决
    pace.js 自动加载进度条插件的简单使用教程
    git push 报错 ERROR: Permission to xxx.git denied to someuser
    Laravel 框架对于分表进行统计合并查询的思路
    解决tail命令提示“tail: inotify 资源耗尽,无法使用 inotify 机制,回归为 polling 机制”
    phpredis 报错 “Function Redis::setTimeout() is deprecated” 解决方法
    laravel 5.5.39 升级到 5.5.45 出现 cookie 序列化异常问题的解决
    vue.js 实战 todo list
    BootstrapVue 安装指南
    05js语法检查、js兼容性处理
  • 原文地址:https://www.cnblogs.com/ac-evil/p/14490076.html
Copyright © 2011-2022 走看看