Description
A国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
Input
第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。
接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。
Output
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。
Sample Input 1
4 3 1 2 4 2 3 3 3 1 1 3 1 3 1 4 1 3
Sample Output 1
3 -1 3
Hint
对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q < 1,000;
对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q < 1,000;
对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q < 30,000,0 ≤ z ≤ 100,000。
Kruskal构建最大生成树,要经过的边一定在这棵树上(可用反证法证明)
之后LCA处理询问即可
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #include<vector> #include<algorithm> using namespace std; const int maxn = 10005, maxm = 50005, inf = 0x3f3f3f3f; struct edge{ int a, b, w; bool operator <(const edge& b) const { return w>b.w; } } e[maxm]; int fir[maxn], ne[maxn*2], to[maxn*2], w[maxn*2], np; void add(int x, int y, int z) { ne[++np] = fir[x]; fir[x] = np; to[np] = y; w[np] = z; } int fa[maxn]; int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); } int n, m; void kruskal() { sort(e, e+m); for(int i=0; i<m; i++) { int u = e[i].a, v = e[i].b; if(find(u) == find(v)) continue; fa[find(u)] = find(v); add(u, v, e[i].w); add(v, u, e[i].w); } } int f[maxn][20], dist[maxn][20]; int dep[maxn]; void dfs(int u, int F, int depth, int wf) { dep[u] = depth; f[u][0] = F; dist[u][0] = wf; for(int i=1; i<=18; i++) f[u][i] = f[f[u][i-1]][i-1], dist[u][i] = min( dist[u][i-1], dist[f[u][i-1]][i-1]); for(int i=fir[u]; i; i=ne[i]) if(to[i] != F) dfs(to[i], u, depth+1, w[i]); } int LCA(int x, int y) { if(find(x) != find(y)) return -1; if(dep[x]<dep[y]) swap(x, y); int ans = inf; for(int i=18; i>=0; i--) if((dep[x]-dep[y])&(1<<i)) { ans = min(ans, dist[x][i]); x = f[x][i]; } if(x == y) return ans; for(int i=18; i>=0; i--) if(f[x][i] != f[y][i]) { ans = min(ans, min(dist[x][i], dist[y][i])); x = f[x][i]; y = f[y][i]; } return min(ans, min(dist[x][0], dist[y][0])); } int main() { scanf("%d%d", &n, &m); for(int i=1; i<=n; i++) fa[i] = i; for(int i=0, x, y, z; i<m ;i++) { scanf("%d%d%d", &x, &y, &z); e[i]=(edge){x, y, z}; } kruskal(); for(int i=1; i<=n; i++) if(!dep[i]) dfs(i, 0, 1, inf); int q; scanf("%d", &q); while(q--){ int x, y; scanf("%d%d", &x, &y); printf("%d ", LCA(x, y)); } return 0; }