zoukankan      html  css  js  c++  java
  • AGC002

    D - Stamp Rally

    • 题意:给定(n<=100 000)个点的无向图,有(m<=100 000)条边,输入(m)条边,第(i)条边,边权是(i),有(q <= 100 000)个询问,每个询问给出两个点(x)(y),和数量(z),求从(x)点和(y)点出发,任意恰好走(z)条边,求经过的最大边权最小是多少。
    • 题解:用了黑科技克鲁斯卡尔重构树,好像用可持久化并查集和整体二分也能过,因为感觉克鲁斯卡尔重构树较为容易掌握,就先学了这个。克鲁斯卡尔重构树就是在克鲁斯卡尔最小生成树上,按边权从小到大的顺序,新增(n-1)个点,将每条边的两个端点的父亲节点连向新增的点,新增的点权即为边权。
    • 代码:
    #include <iostream>
    #include <vector>
    using namespace std;
    const int N = 1e6 + 9;
    const int inf = 0x3f3f3f3f;
    vector<int>G[N];
    int f[N];
    int Find(int x) {return f[x] == x?x:f[x] = Find(f[x]);}
    int V[N];
    int sz[N];
    int fa[N][20];
    void dfs(int u, int father) {
    	fa[u][0] = father;
    	for (int i = 1; i <= 17; i++) {
    		fa[u][i] = fa[fa[u][i-1]][i-1];
    	}
    	for (auto v : G[u]) {
    		if (father == v)continue;
    		dfs(v, u);
    		sz[u] += sz[v];
    	}
    	if (sz[u] == 0)sz[u]++;
    	return ;
    }
    bool check(int x, int y, int mid, int cnt) {
    	for (int i = 17; i >= 0; i--) {
    		if (V[fa[x][i]] <= mid)x = fa[x][i];
    		if (V[fa[y][i]] <= mid)y = fa[y][i];
    	}
    	int t = 0;
    	if (x == y) t = sz[x];
    	else t = sz[x] + sz[y];
    	if (t < cnt)return 1;
    	else return 0;
    }
    int main() {
    	int n, m;
    	ios::sync_with_stdio(0);
    	cin >> n >> m;
    	for (int i = 1; i <= n + n; i++)f[i] = i;
    	int cnt = 0;
    	V[0] = inf;
    	for (int i = 1;  i <= m; i++) {
    		int u, v, w;
    		cin >> u >> v;
    		int fx = Find(u);
    		int fy = Find(v);
    		if (fx != fy && cnt <= n-1){
    			cnt++;
    			int node = n + cnt;
    			V[node] = i;
    			G[node].push_back(fx);
    			G[node].push_back(fy);
    			f[fx] = node;
    			f[fy] = node;
    		}
    	}
    	dfs(n + cnt, 0);
    	int q;
    	cin >> q;
    	while (q--) {
    		int u, v, z;
    		cin >> u >> v >> z;
    		int l = 0, r = n* 2;
    		int ans;
    		while (l < r) {
    			int mid = l + r >> 1;			
    			if (check(u, v, mid, z)) {
    				l = mid + 1;
    			} else {
    				ans = r;r = mid;
    			}
    		}
    		cout << l << endl;
    	}
    }
    
  • 相关阅读:
    Educational Codeforces Round 86 (Rated for Div. 2) D. Multiple Testcases
    Educational Codeforces Round 86 (Rated for Div. 2) C. Yet Another Counting Problem
    HDU
    HDU
    HDU
    HDU
    Good Bye 2019 C. Make Good (异或的使用)
    Educational Codeforces Round 78 (Rated for Div. 2) C. Berry Jam
    codeforces 909C. Python Indentation
    codeforces1054 C. Candies Distribution
  • 原文地址:https://www.cnblogs.com/Xiao-yan/p/14339128.html
Copyright © 2011-2022 走看看