zoukankan      html  css  js  c++  java
  • 洛谷 P1967

    题目链接:P1967 货车运输

    题目大意

    开局一张图装备全靠打

    题目给了你一张图,然后呢, 让你找两点之间的路径,使路径上的最小值最大.(大概就是这个意思)

    solution

    思路

    最小值最大? 二分? 复杂度不对啊

    Floyd? 复杂度更不对了!

    那我们怎么想呢? 贪心? 对, 就是贪心!

    我们建一颗最大生成树,也就是最大瓶颈生成树(如果会生成树,这个地方就明白了为什么建最大生成树是对的), 树上两点间的路径的最小值一定是最大值

    那建完树之后,我们怎么做呢?树剖?没必要,太浪费了,毕竟连修改都木有

    我们简单的倍增一下就可以了,树上两点之间路径是唯一的,所以我们可以 (LCA) ,记录一下,树上倍增求最小值, 在处理 (LCA) 的时候顺便处理最小值即可

    细节

    数据非常的毒瘤啊, 有时候图还不是一张连通图

    那我们怎么办? 其实很简单,我们在建树的时候,用并查集存过了, 所以我们在求 (LCA) 的时候求一下两点在没在同一个集合里就行了

    code:

    /**
     *    Author: Alieme
     *    Data: 2020.8.25
     *    Problem: Luogu P1967
     *    Time: O(nlogn)
     */
    #include <cstdio>
    #include <iostream>
    #include <string>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    #define int long long
    #define rr register
    
    #define inf 1e9
    #define MAXN 100010
    
    using namespace std;
    
    inline int read() {
    	int s = 0, f = 0;
    	char ch = getchar();
    	while (!isdigit(ch)) f |= ch == '-', ch = getchar();
    	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
    	return f ? -s : s;
    }
    
    void print(int x) {
    	if (x < 0) putchar('-'), x = -x;
    	if (x > 9) print(x / 10);
    	putchar(x % 10 + 48);
    }
    
    struct Gragh {
    	int u;
    	int v;
    	int w;
    	Gragh() {}
    	Gragh(int U, int V, int W) { u = U, v = V, w = W;}
    	bool operator < (const Gragh &b) const{return w > b.w;} // 贪心
    }a[MAXN];
    
    struct Edge {
    	int nxt;
    	int to;
    	int val;
    	Edge() {}
    	Edge(int Nxt, int To, int Val) {nxt = Nxt, to = To, val = Val;}
    }e[MAXN];
    
    int n, m, q, tot;
    
    int fath[MAXN], head[MAXN], dep[MAXN];
    
    int fa[MAXN][30], w[MAXN][30];
    
    bool vis[MAXN];
    
    inline void add(int from, int to, int val) {
    	e[++tot] = Edge(head[from], to, val);
    	head[from] = tot;
    }
    
    int find(int x) { // 并查集
    	if (x != fath[x]) fath[x] = find(fath[x]);
    	return fath[x];
    }
    
    inline void Union(int x, int y) { fath[find(x)] = find(y);}
    
    inline void klus() {  // klus建最大生成树
    	sort(a + 1, a + 1 + m);
    	for (rr int i = 1; i <= n; i++) fath[i] = i;
    	for (rr int i = 1; i <= m; i++) 
    		if (find(a[i].u) != find(a[i].v)) {
    			Union(a[i].u, a[i].v);
    			add(a[i].u, a[i].v, a[i].w);
    			add(a[i].v, a[i].u, a[i].w);
    		}
    }
    
    void dfs(int x) { // LCA的dfs
    	vis[x] = 1;
    	for (rr int i = head[x]; i; i = e[i].nxt) {
    		int to = e[i].to;
    		if (vis[to]) continue;
    		dep[to] = dep[x] + 1;
    		fa[to][0] = x;
    		w[to][0] = e[i].val;
    		dfs(to);
    	}
    }
    
    inline int LCA(int u, int v) { // 树上倍增找最小值
    	if (find(u) != find(v)) return -1; // 两点不联通
    	int ans = inf;
    	if (dep[u] > dep[v]) swap(u, v);
    	for (rr int i = 20; i >= 0; i--) 
    		if (dep[fa[v][i]] >= dep[u]) {
    			ans = min(ans, w[v][i]);
    			v = fa[v][i];
    		}
    	if (u == v) return ans;
    	for (rr int i = 20; i >= 0; i--) {
    		if (fa[u][i] != fa[v][i]) {
    			ans = min(ans, min(w[u][i], w[v][i]));
    			u = fa[u][i];
    			v = fa[v][i];
    		}
    	}
    	ans = min(ans, min(w[u][0], w[v][0]));
    	return ans;
    }
    
    signed main() {
    	n = read();
    	m = read();
    	for (rr int i = 1; i <= m; i++) {
    		int u = read();
    		int v = read();
    		int w = read();
    		a[i] = Gragh(u, v, w);
    	}
    	klus();	
    //  LCA初始化
    	for (rr int i = 1; i <= n; i++) 
    		if (!vis[i]) {
    			dep[i] = 1;
    			dfs(i);
    			fa[i][0] = i;
    			w[i][0] = inf;
    		}
    	for (rr int i = 1; i <= 20; i++) 
    		for (rr int j = 1; j <= n; j++) {
    			fa[j][i] = fa[fa[j][i - 1]][i - 1];
    			w[j][i] = min(w[j][i - 1], w[fa[j][i - 1]][i - 1]);
    		}
    
    	q = read();
    	while (q--) {
    		int x = read();
    		int y = read();
    		print(LCA(x, y));
    		puts("");
    	}
    }
    
    时间会刺破青春表面的彩饰,会在美人的额上掘深沟浅槽;会吃掉稀世之珍!天生丽质,什么都逃不过他那横扫的镰刀。 博主写的那么好,就不打赏一下么(打赏在右边)
  • 相关阅读:
    安卓远程工具介绍及下载地址
    kylinos-kysec介绍
    远程控制工具ToDesk介绍
    kylinos桌面和服务器系统重置密码
    APT仓库目录和repository目录结构
    使用LVM实现动态磁盘管理
    如何实现访问http自动跳转https
    TypeScript学习 ———— 四、泛型
    TypeScript学习 ———— 三、function
    TypeScript学习 ———— 二、接口
  • 原文地址:https://www.cnblogs.com/lieberdq/p/13560058.html
Copyright © 2011-2022 走看看