P1967 货车运输

题目描述

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。

【题解】

最大生成树+树上倍增,证明可用反证法或者显然法(唔)

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define min(a, b) ((a) < (b) ? (a) : (b)) inline void read(int &x)
{
x = ;char ch = getchar(), c = ch;
while(ch < '' || ch > '') c = ch, ch = getchar();
while(ch <= '' && ch >= '') x = x * + ch - '', ch = getchar();
if(c == '-') x = -x;
} inline void swap(int &a, int &b)
{
int tmp = a;a = b;b = tmp;
} const int MAXN = + ;
const int MAXM = + ;
const int INF = 0x3f3f3f3f; int n,m,u[MAXM],v[MAXM],w[MAXM],cnt[MAXM],q,s,t,fa[MAXN],b[MAXM]; bool cmp(int a, int b)
{
return w[a] > w[b];
} struct Edge
{
int u,v,w,next;
Edge(int _u, int _v, int _w, int _next){u = _u, v = _v, w = _w, next = _next;}
Edge(){}
}edge[MAXN << ];
int head[MAXN], cntt;
inline void insert(int a, int b, int c)
{
edge[++cntt] = Edge(a,b,c,head[a]);
head[a] = cntt;
} int deep[MAXN], p[][MAXN], mi[][MAXN]; void dfs(int u)
{
b[u] = ;
for(register int pos = head[u];pos;pos = edge[pos].next)
{
int v = edge[pos].v;
if(b[v])continue;
deep[v] = deep[u] + ;
p[][v] = u;
mi[][v] = edge[pos].w;
dfs(v);
}
} void yuchuli()
{
int M = ;
while(( << M) <= n) ++ M;
-- M;
for(register int i = ;i <= M;++ i)
for(register int j = ;j <= n;++ j)
p[i][j] = p[i - ][p[i - ][j]];
for(register int i = ;i <= M;++ i)
for(register int j = ;j <= n;++ j)
mi[i][j] = min(mi[i - ][p[i - ][j]], mi[i - ][j]);
} int LCA(int va, int vb)
{
if(deep[va] < deep[vb]) swap(va, vb);
int M = ;
while(( << M) <= n)++ M;
-- M;
for(register int i = M;i >= ;-- i)
if(deep[vb] + ( << i) <= deep[va])
va = p[i][va];
if(va == vb)return va;
M = ;
while(( << M) <= deep[va]) ++ M;
-- M;
for(register int i = M;i >= ;-- i)
if(p[i][va] != p[i][vb])
{
va = p[i][va];
vb = p[i][vb];
}
return p[][va];
} int find(int x)
{
return x == fa[x] ? x : fa[x] = find(fa[x]);
} int main()
{
read(n), read(m);
for(register int i = ;i <= m;++i)
read(u[i]), read(v[i]), read(w[i]), cnt[i] = i;
for(register int i = ;i <= n;++ i)
fa[i] = i;
std::sort(cnt + , cnt + + m, cmp);
for(register int i = ;i <= m;++i)
{
int f1 = find(u[cnt[i]]), f2 = find(v[cnt[i]]);
if(f1 != f2)
{
fa[f1] = f2;
insert(u[cnt[i]], v[cnt[i]], w[cnt[i]]);
insert(v[cnt[i]], u[cnt[i]], w[cnt[i]]);
}
}
for(register int i = ;i <= n;++ i)
{
if(!b[i])
{
deep[i] = ;
dfs(i);
}
}
yuchuli();
read(q);
int s,t;
int M = ;
while(( << M) <= n) ++ M;
-- M;
for(register int i = ;i <= q;++ i)
{
read(s), read(t);
int f1 = find(s), f2 = find(t);
if(f1 != f2)
{
printf("-1\n");
continue;
}
int lca = LCA(s, t);
int mi1 = INF, mi2 = INF;
for(register int j = M;j >= ;-- j)
if(p[j][s] && deep[p[j][s]] >= deep[lca])
{
mi1 = min(mi1, mi[j][s]);
s = p[j][s];
}
for(register int j = M;j >= ;-- j)
if(p[j][t] && deep[p[j][t]] >= deep[lca])
{
mi2 = min(mi2, mi[j][t]);
t = p[j][t];
}
printf("%d\n", min(mi1, mi2));
}
return ;
}

NOIP2013Day1T3

05-11 22:07