zoukankan      html  css  js  c++  java
  • 洛谷P1967 货车运输

    (large{题目链接})
    (\)
    (Large extbf{Solution: } large{注意到两地之间的路径可能有多条,又要使路径上的边权最小最大,想到最大生成树。\先建树,然后树上倍增即可。\值得注意的是,图中所有点不一定联通,所以搜索时要谨慎。})

    (Large extbf{Code: })

    #include <bits/stdc++.h>
    #define gc() getchar() 
    #define rep(i, a, b) for (int i = (a); i <= (b); ++i)
    using namespace std;
    const int N = 1e4 + 5;
    const int M = 5e4 + 5;
    const int inf = 0x7fffffff;
    int n, m, cnt, f[N], h[N], head[N], vis[N], lg[N], dep[N], Min[N][20], fa[N][20];
    
    struct Edge {
    	int fro, to, val;
    }E[M];
    
    struct EDGE {
    	int to, next, val;	
    }e[N << 1];
    
    inline int read() {
    	int x = 0;
    	char ch = gc();
    	while (!isdigit(ch)) ch = gc();
    	while (isdigit(ch)) x = x * 10 + ch - '0', ch = gc();
    	return x; 
    }
    
    inline void add(int x, int y, int w) {
    	e[++cnt].to = y;
    	e[cnt].next = head[x];
    	e[cnt].val = w;
    	head[x] = cnt;
    }
    
    inline int find(int x) {
    	if (x == f[x]) return x;
    	return f[x] = find(f[x]);
    }
    
    inline bool cmp(Edge a, Edge b) {
    	return a.val > b.val;	
    }
    
    inline void Kruskal() {
    	rep(i, 1, n) f[i] = i;
    	sort(E + 1, E + m + 1, cmp);
    	int tot = 0;
    	for (int i = 1; i <= m; ++i) {
    		int u = find(E[i].fro), v = find(E[i].to);
    		if (u != v) f[v] = u, ++tot, add(E[i].fro, E[i].to, E[i].val), add(E[i].to, E[i].fro, E[i].val);
    		if (tot == n - 1) break;
    	}
    	return;
    }
    
    inline void dfs(int x, int fat, int w) {
    	vis[x] = 1;
    	fa[x][0] = fat;
    	Min[x][0] = w;
    	dep[x] = dep[fat] + 1;
    	for (int i = 1; (1 << i) <= dep[x]; ++i) {
    		fa[x][i] = fa[fa[x][i - 1]][i - 1];
    		Min[x][i] = min(Min[x][i - 1], Min[fa[x][i - 1]][i - 1]);
    	}
    	for (int i = head[x]; i ; i = e[i].next) if (e[i].to != fat) dfs(e[i].to, x, e[i].val);
    }
    
    inline int sol(int x, int y) {
    	if (find(x) != find(y)) return -1;
    	int ans = inf;
    	if (dep[x] < dep[y]) swap(x, y);
    	while (dep[x] > dep[y]) ans = min(ans, Min[x][lg[dep[x] - dep[y]]]), x = fa[x][lg[dep[x] - dep[y]]];
    	if (x == y) return ans;
    	for (int i = lg[dep[x]]; i >= 0; --i) if (fa[x][i] != fa[y][i]) ans = min(ans, min(Min[x][i], Min[y][i])), x = fa[x][i], y = fa[y][i];
    	ans = min(ans, min(Min[x][0], Min[y][0]));
    	return ans;
    }
    
    int main() {
    	n = read(), m = read();
    	int x, y, w;
    	rep(i, 2, n) lg[i] = lg[i >> 1] + 1;
    	for (int i = 1; i <= m; ++i) E[i].fro = read(), E[i].to = read(), E[i].val = read();
    	Kruskal();
    	rep(i, 1, 20) rep(j, 1, n) Min[i][j] = inf;
    	rep(i, 1, n)
    		if (!dep[i]) {
    			dep[i] = 0;
    			dfs(i, 0, inf);
    		}
    	m = read();
    	while (m--) {
    		x = read(), y = read();
    		if (!vis[x] || !vis[y]) { puts("-1"); continue; }
    		printf("%d
    ", sol(x, y));
    	}
    	return 0;
    }
    
  • 相关阅读:
    娓娓道来c指针 (4)解析c的声明语句
    Snail—UI学习之UITextField
    E
    Qt录音机
    著名的英文搜索引擎
    java中Map,List与Set的差别
    Android图片处理:识别图像方向并显示
    Unity3D中组件事件函数的运行顺序
    Android屏幕density, dip等相关概念总结
    Codeforces Round #257 (Div. 2)
  • 原文地址:https://www.cnblogs.com/Miraclys/p/12567988.html
Copyright © 2011-2022 走看看