1. 程式人生 > >洛谷 #1967. 貨車運輸

洛谷 #1967. 貨車運輸

題意

在圖上從x到y找一條簡單路徑,使得路徑上最小值最大

暴力會T

題解

因為需要的是較大的那些邊,故可以求最大生成樹,然後LCA

除錯記錄

陣列開小了

#include <cstdio>
#include <algorithm>
#include <cstring>
#define INF 0x3f3f3f3f
#define maxn 50005

using namespace std;

int n, m, q, u, v;

struct Node{
	int u, v, l;
}E[maxn];

struct node{
int to, next, l; }e[maxn << 1]; int tot = 0, head[maxn]; void addedge(int u, int v, int l){ e[++tot] = (node){v, head[u], l}; head[u] = tot; } int f[maxn]; int getf(int x){ if (f[x] != x) f[x] = getf(f[x]); return f[x]; } bool cmp(Node a, Node b){ return a.l > b.l; } void Kruskal(){ sort
(E + 1, E + m + 1, cmp); for (int i = 1; i <= n; i++) f[i] = i; for (int i = 1; i <= m; i++){ if (getf(E[i].u) != getf(E[i].v)){ f[getf(E[i].u)] = getf(E[i].v); addedge(E[i].u, E[i].v, E[i].l); addedge(E[i].v, E[i].u, E[i].l); } } } int fa[maxn][21], l[maxn][21], dep[maxn]; bool
vis[maxn]; void dfs(int cur){ vis[cur] = true; for (int i = head[cur]; i; i = e[i].next){ if (!vis[e[i].to]){ fa[e[i].to][0] = cur; l[e[i].to][0] = e[i].l; dep[e[i].to] = dep[cur] + 1; dfs(e[i].to); } } } int LCA(int x, int y){ if (getf(x) != getf(y)) return -1; if (dep[x] < dep[y]) swap(x, y); int ans = INF; for (int i = 20; i >= 0; i--){ if (dep[fa[x][i]] >= dep[y]){ ans = min(ans, l[x][i]); x = fa[x][i]; } } if (x == y) return ans; for (int i = 20; i >= 0; i--){ if (fa[x][i] != fa[y][i]){ ans = min(ans, min(l[x][i], l[y][i])); x = fa[x][i], y = fa[y][i]; } } ans = min(ans, min(l[x][0], l[y][0])); return ans; } int main(){ scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].l); Kruskal(); memset(vis, false, sizeof vis); for (int i = 1; i <= n; i++){ if (!vis[i]){ dep[i] = 1; l[i][0] = INF; fa[i][0] = i; dfs(i); } } for (int i = 1; i <= 20; i++){ for (int j = 1; j <= n; j++){ fa[j][i] = fa[fa[j][i - 1]][i - 1]; l[j][i] = min(l[j][i - 1], l[fa[j][i - 1]][i - 1]); } } scanf("%d", &q); while (q--){ scanf("%d%d", &u, &v); printf("%d\n", LCA(u, v)); } return 0; }