记录编号 204244 评测结果 AAAAAAAAAA
题目名称 [NOIP 2013]货车运输 最终得分 100
用户昵称 Gravatar啊吧啦吧啦吧 是否通过 通过
代码语言 C++ 运行时间 0.083 s
提交时间 2015-11-04 07:52:21 内存使用 3.53 MiB
显示代码纯文本
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <climits>
#define file
#define rep(i, l, r) for (long long i = (l); i <= (r); ++i)

using namespace std;
typedef vector<long long> vll;
const long long MAXM(50010);
struct tree {
	long long u, v, w;
} edge[MAXM];

const long long MAXN(10010), INF(LLONG_MAX / 3);
long long n,m,as[MAXN],ufs(long long),fa[MAXN],cost[MAXN],anc[MAXN][10],
dig[MAXN],maxcost[MAXN][10],q;
bool cmp(const tree&, const tree&), vis[MAXN];
vector<long long> gtv[MAXN], gtu[MAXN];
void build_tree(long long);
inline void preprocess();
inline long long read(), query(long long, long long);

int main() {
#ifdef file
	freopen("truck.in", "r", stdin);
	freopen("truck.out", "w", stdout);
#endif
	n = read();
	m = read();
	rep(i, 1, m) {
		edge[i].u = read();
		edge[i].v = read();
		edge[i].w = read();
	}
	sort(edge + 1, edge + m + 1, cmp);
	rep(i, 1, n)
		as[i] = i;
	long long cnt = 0;
	rep(i, 1, m) {
		long long fx = ufs(edge[i].u), fy = ufs(edge[i].v);
		if (fx != fy) {
			gtv[edge[i].u].push_back(i);
			gtu[edge[i].v].push_back(i);
			as[fx] = fy;
			++cnt;
			if (cnt >= n - 1)
				break;
		}
	}
	rep(i, 1, n)
		if (! vis[i]) {
			dig[i] = 0;
			build_tree(i);
		}
	preprocess();
	for (q = read(); q; --q) {
		long long x, y;
		x = read();
		y = read();
		printf("%lld\n", query(x, y));
	}
//	for (; ; );
}

bool cmp(const tree &a, const tree &b) {
	return a.w > b.w;
}

long long ufs(long long x) {
	return (x == as[x]) ? x : (as[x] = ufs(as[x]));
}

void build_tree(long long root) {
	vis[root] = true;
	for (vll::iterator it = gtv[root].begin(); it != gtv[root].end(); ++it)
		if (! vis[edge[*it].v]) {
			cost[edge[*it].v] = edge[*it].w;
			fa[edge[*it].v] = root;
			dig[edge[*it].v] = dig[root] + 1;
			build_tree(edge[*it].v);
		}
	for (vll::iterator it = gtu[root].begin(); it != gtu[root].end(); ++it)
		if (! vis[edge[*it].u]) {
			cost[edge[*it].u] = edge[*it].w;
			fa[edge[*it].u] = root;
			dig[edge[*it].u] = dig[root] + 1;
			build_tree(edge[*it].u);
		}
}

inline void preprocess() {
	for (long long i = 1; i <= n; ++i) {
		anc[i][0] = fa[i];
		maxcost[i][0] = cost[i];
		for (long long j = 1; (1 << j) < n; ++j)
			anc[i][j] = -1;
	}
	for (long long j = 1; (1 << j) < n; ++j)
		for (long long i = 1; i <= n; ++i)
			if (anc[i][j - 1] != -1) {
				long long a = anc[i][j - 1];
				anc[i][j] = anc[a][j - 1];
				maxcost[i][j] = min(maxcost[i][j - 1], maxcost[a][j - 1]);
			}
}

inline long long read() {
	long long x = 0;
	char c;
	while (! isdigit(c = getchar()));
	while (isdigit(c)) {
		x = x * 10 + c - '0';
		c = getchar();
	}
	return x;
}

inline long long query(long long p, long long q) {
	if (ufs(q) != ufs(p))
		return -1;
	long long log;
	if (dig[p] < dig[q])
		swap(p, q);
	for (log = 1; (1 << log) <= dig[p]; ++log);
	--log;
	long long ans = INF;
	for (long long i = log; i >= 0; --i)
		if (dig[p] - (1 << i) >= dig[q]) {
			ans = min(ans, maxcost[p][i]);
			p = anc[p][i];
		}
	if (p == q)	//LCA->p
		return ans;
	for (long long i = log; i >= 0; --i)
		if (anc[p][i] != -1 && anc[p][i] != anc[q][i]) {
			ans = min(ans, maxcost[p][i]);
			p = anc[p][i];
			ans = min(ans, maxcost[q][i]);
			q = anc[q][i];
		}
	ans = min(ans, cost[p]);
	ans = min(ans, cost[q]);
	return ans;	//LCA->fa[p]
}