• [LuoGu2245]星际导航


    Description

    [LuoGu2245]星际导航

    Solution

    好像叫作最小瓶颈路问题
    就是把原图求最小生成树,然后在树上跑( ext{LCA})的最大值
    如果不在一个一颗树上,就输出( ext{impossible})
    玄学证明不会

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define N 800010
    struct rec {
    	int nxt, ver, val;
    } t[N];
    struct Rec {
    	int u, v, w;
    } e[N];
    int n, m, q, cnt, tot, u, v;
    int fa[N], head[N], deep[N], f[N][21], h[N][21];
    inline int read() {
    	int s = 0, w = 1;
    	char c = getchar();
    	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
    	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
    	return s * w;
    }
    int find(int x) {
    	if (fa[x] == x) return x;
    	return fa[x] = find(fa[x]);
    }
    inline void Merge(int x, int y) {
    	fa[find(x)] = find(y);
    }
    inline bool cmp(Rec x, Rec y) {
    	return x.w < y.w;
    }
    inline void add(int u, int v, int w) {
    	t[++cnt].nxt = head[u], t[cnt].ver = v, t[cnt].val = w, head[u] = cnt;
    }
    inline void Init() {
    	for (register int i = 1; i <= n; i++)
    		fa[i] = i;
    }
    inline void kruskal() {
    	sort(e + 1, e + m + 1, cmp);
    	for (register int i = 1; i <= m; i++) {
    		int eu = find(e[i].u), ev = find(e[i].v);
    		if (eu == ev) continue;
    		add(e[i].u, e[i].v, e[i].w), add(e[i].v, e[i].u, e[i].w);
    		fa[ev] = eu;
    		++tot;
    		if (tot == n - 1) break;
    	}
    }
    void DFS(int u, int fa, int w) {
    	deep[u] = deep[fa] + 1;
    	f[u][0] = fa, h[u][0] = w;
    	for (register int i = 1; i <= 20; i++)
    		f[u][i] = f[f[u][i - 1]][i - 1],
    		h[u][i] = max(h[u][i - 1], h[f[u][i - 1]][i - 1]);
    	for (register int i = head[u]; i; i = t[i].nxt) {
    		int v = t[i].ver;
    		if (v != fa)
    			DFS(v, u, t[i].val);
    	}
    }
    inline int LCA(int u, int v) {
    	int ans = 0;
    	if (deep[u] < deep[v]) swap(u, v);
    	for (register int i = 20; i >= 0; i--)
    		if (deep[f[u][i]] >= deep[v]) {
    			ans = max(ans, h[u][i]);
    			u = f[u][i];
    		}
    	if (u == v) return ans;
    	for (register int i = 20; i >= 0; i--)
    		if (f[u][i] != f[v][i]) {
    			ans = max(ans, h[u][i]), ans = max(ans, h[v][i]);
    			u = f[u][i], v = f[v][i];
    		}
    	ans = max(ans, h[u][0]), ans = max(ans, h[v][0]);
    	return ans;
    }
    int main() {
    	//freopen("a.in", "r", stdin);
    	//freopen("1.out", "w", stdout);
    	n = read(), m = read();
    	for (register int i = 1; i <= m; i++)
    		e[i].u = read(), e[i].v = read(), e[i].w = read();
    	Init();
    	kruskal();
    	for (register int i = 1; i <= n; i++)
    		if (!deep[i])
    			DFS(i, 0, 0);
    	q = read();
    	for (register int i = 1; i <= q; i++) {
    		u = read(), v = read();
    		if (find(u) != find(v))
    			printf("impossible
    ");
    		else
    			printf("%d
    ", LCA(u, v));
    	}
    	return 0;
    }
    
    只要有想见的人,就不是孤身一人了。
  • 相关阅读:
    Visual Studio 2008 每日提示(四)
    修改XP注册到用户名和公司组织名
    Visual Studio技巧之打造拥有自己标识的代码模板
    收集的学习资料
    多个记录更新(存储过程)
    '1,2,3,68,10'转换为'1,2,3,6,7,8,10'
    .NET程序员面试的题一部 (转)
    [.net]DataGrid中绑定DropDownList[转]
    使用DELETE与TRUNCATE删除表所有行的区别
    sysobjects 各列的含义
  • 原文地址:https://www.cnblogs.com/Agakiss/p/11827947.html
Copyright © 2020-2023  润新知