zoukankan      html  css  js  c++  java
  • 【最小生成树+LCA】Imperial roads

    http://codeforces.com/gym/101889
    I

    先跑一遍最小生成树,把经过的边和答案记录下来
    对于每个询问的边,显然如果处于MST中,答案不变
    如果不在MST中,假设这条边连上了,那么就会和原本的MST形成环,删除这个环中权值最大的边就是答案
    处理的时候,可以用LCA维护MST:给出边的两个节点u、v,那么u和v的LCA路径上的最大值边就是环中权值最大的边

    代码:

    #include <iostream>
    #include <cstring>
    #include <cmath>
    #include <vector>
    #include <algorithm>
    #include <map>
    using namespace std;
    typedef long long ll;
    const int MAX_V = 100005;
    const int MAX_E = 200005;
    const int MAX_N = 100005;
    struct LCA_Online {
    	int N, M, E, root, in[MAX_N], head[MAX_N];
    	int f[MAX_N][30], c[MAX_N][30], depth[MAX_N];
    	struct Edge {
    		int to, next, cost;
    	} es[MAX_N << 2];
    	void addEdge(int u, int v, int w) {
    		es[E].to = v;
    		es[E].next = head[u];
    		es[E].cost = w;
    		head[u] = E++;
    		in[v]++;
    	}
    	void init(int N) {
    		this->N = N;
    		this->M = floor(log2(double(N)));
    		this->E = 0;
    		this->root = 0;
    		memset(head, -1, sizeof head);
    		memset(f, 0, sizeof f);
    		memset(c, 0, sizeof c);
    		memset(in, 0, sizeof in);
    	}
    	void dfs(int u) {
    		for (int j = 1; j <= M; j++) {
    			f[u][j] = f[f[u][j - 1]][j - 1];
    			c[u][j] = max(c[u][j - 1], c[f[u][j - 1]][j - 1]);
    		}
    		for (int i = head[u]; ~i; i = es[i].next) {
    			int v = es[i].to;
    			int w = es[i].cost;
    			if (v != f[u][0]) {
    				depth[v] = depth[u] + 1;
    				f[v][0] = u;
    				c[v][0] = w;
    				dfs(v);
    			}
    		}
    	}
    	void run() {
    		dfs(1);
    	}
    	int LCA(int u, int v) {
    		if (depth[u] < depth[v]) {
    			swap(u, v);
    		}
    		int res = 0;
    		int d = depth[u] - depth[v];
    		for (int i = 0; i <= M; i++) {
    			if ((1 << i) & d) {
    				res = max(res, c[u][i]);
    				u = f[u][i];
    			}
    		}
    		if (u == v) {
    			return res;
    		}
    		for (int i = M; i >= 0; i--) {
    			if (f[u][i] != f[v][i]) {
    				res = max(res, max(c[u][i], c[v][i]));
    				u = f[u][i];
    				v = f[v][i];
    			}
    		}
    		return max(res, max(c[u][0], c[v][0]));
    	}
    } lca;
    struct Kruskal {
    	struct Edge {
    		int from, to, cost;
    		bool operator< (const Edge& e) const {
    			return cost < e.cost;
    		}
    	} es[MAX_E];
    	int V, E, p[MAX_V];
    	void init(int V) {
    		this->V = V;
    		this->E = 0;
    		for (int i = 0; i < V; i++) {
    			p[i] = i;
    		}
    	}
    	void addEdge(int u, int v, int w) {
    		es[E].from = u;
    		es[E].to = v;
    		es[E].cost = w;
    		E++;
    	}
    	int find(int x) {
    		return x == p[x] ? x : p[x] = find(p[x]);
    	}
    	void unite(int x, int y) {
    		p[find(y)] = find(x);
    	}
    	ll kruskal() {
    		ll sum = 0;
    		sort(es, es + E);
    		for (int i = 0; i < E; i++) {
    			Edge &e = es[i];
    			if (find(e.from) != find(e.to)) {
    				sum += e.cost;
    				unite(e.from, e.to);
    				lca.addEdge(e.from, e.to, e.cost);
    				lca.addEdge(e.to, e.from, e.cost);
    			}
    		}
    		return sum;
    	}
    } kru;
    map<pair<int, int>, int> cost;
    int main() {
    	int N, R, Q;
    	scanf("%d%d", &N, &R);
    	kru.init(N);
    	lca.init(N);
    	for (int i = 0, u, v, w; i < R; i++) {
    		scanf("%d%d%d", &u, &v, &w);
    		if (u > v) {
    			swap(u, v);
    		}
    		cost[make_pair(u, v)] = w;
    		//cost[make_pair(v, u)] = w;
    		kru.addEdge(u, v, w);
    		//kru.addEdge(v, u, w);
    	}
    	ll ans = kru.kruskal();
    	lca.run();
    	scanf("%d", &Q);
    	while (Q--) {
    		int u, v;
    		scanf("%d%d", &u, &v);
    		if (u > v) {
    			swap(u, v);
    		}
    		printf("%I64d
    ", ans + cost[make_pair(u, v)] - lca.LCA(u, v));
    	}
    }
  • 相关阅读:
    渣渣小本求职复习之路每天一博客系列——Java基础(9)
    渣渣小本求职复习之路每天一博客系列——Java基础(8)
    渣渣小本求职复习之路每天一博客系列——Java基础(7)
    渣渣小本求职复习之路每天一博客系列——Java基础(6)
    渣渣小本求职复习之路每天一博客系列——Java基础(5)
    渣渣小本求职复习之路每天一博客系列——Java基础(4)
    渣渣小本求职复习之路每天一博客系列——Java基础(3)
    渣渣小本求职复习之路每天一博客系列——数据结构与常用算法(3)
    redis常用命令
    redis的sets类型
  • 原文地址:https://www.cnblogs.com/stolf/p/9576581.html
Copyright © 2011-2022 走看看