noip2013D1T3 货车运输
题目描述
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入输出格式
输入格式:
输入文件名为 truck.in。
输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道
路。 接下来 m 行每行 3 个整数 x、 y、 z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意: x 不等于 y,两座城市之间可能有多条道路 。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y 。
输出格式:
输出文件名为 truck.out。
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货
车不能到达目的地,输出-1。
输入输出样例
输入样例#1:
4 3 1 2 4 2 3 3 3 1 1 3 1 3 1 4 1 3输出样例#1:
3 -1 3说明
对于 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。
所有最优路径一定在原图的最大生成树上,不然该路径上最小的边可以更大一些。
倍增求lca的同时求一下当前点到祖先的最小值
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <map> #include <set> #include <vector> #include <queue> #include <cmath> #include <cctype> #include <string> #include <cfloat> #include <stack> #include <cassert> #include <bitset> using namespace std; const int N = 50010; int head[N], rest[N], to[N], w[N], tot, n, m, q, deep[N], fa[N][30], mn[N][30]; void add(int u, int v, int wi) { tot ++; to[tot] = v; w[tot] = wi; rest[tot] = head[u]; head[u] = tot; } void dfs(int u) { for(int i = head[u] ; i ; i = rest[i]) { int v = to[i]; if(v != fa[u][0]) { deep[v] = deep[u] + 1; fa[v][0] = u; mn[v][0] = w[i]; dfs(v); } } } void seq() { for(int j = 1 ; j <= 20 ; j ++) { for(int i = 1 ; i <= n ; i ++) { fa[i][j] = fa[fa[i][j - 1]][j - 1]; mn[i][j] = min(mn[i][j - 1], mn[fa[i][j - 1]][j - 1]); } } } struct E { int u, v, w; } e[N]; bool operator < (E a, E b) { return a.w > b.w; } int acc[N]; int find(int x) {return x == acc[x] ? x : acc[x] = find(acc[x]);}; int ask(int u, int v) { if(find(u) != find(v)) return -1; int ret = 0x3f3f3f3f; if(deep[u] > deep[v]) swap(u, v); for(int i = 20 ; i >= 0 ; i --) { if(deep[fa[v][i]] >= deep[u]) { ret = min(ret, mn[v][i]); v = fa[v][i]; } } if(u == v) return ret; for(int i = 20 ; i >= 0 ; i --) { if(fa[u][i] != fa[v][i]) { ret = min(ret, min(mn[u][i], mn[v][i])); u = fa[u][i]; v = fa[v][i]; } } return min(ret, min(mn[u][0], mn[v][0])); } int main() { // freopen("testdata.in", "r", stdin); scanf("%d%d", &n, &m); for(int i = 1 ; i <= m ; i ++) { scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w); } for(int i = 1 ; i <= n ; i ++) acc[i] = i; sort(e + 1, e + m + 1); for(int i = 1 ; i <= m ; i ++) { if(find(e[i].u) != find(e[i].v)) { acc[find(e[i].u)] = find(e[i].v); add(e[i].u, e[i].v, e[i].w); add(e[i].v, e[i].u, e[i].w); } } memset(mn, 0x3f, sizeof(mn)); dfs(1); seq(); scanf("%d", &q); for(int i = 1, u, v ; i <= q ; i ++) { scanf("%d%d", &u, &v); printf("%d\n", ask(u, v)); } }