【CODEVS 3287】【NOIP2013】火车运输

http://codevs.cn/problem/3287/

题目描述

【CODEVS 3287】【NOIP2013】火车运输 国有 【CODEVS 3287】【NOIP2013】火车运输 座城市,编号从 【CODEVS 3287】【NOIP2013】火车运输【CODEVS 3287】【NOIP2013】火车运输,城市之间有 【CODEVS 3287】【NOIP2013】火车运输 条双向道路。每一条道路对车辆都有重
量限制,简称限重。现在有 【CODEVS 3287】【NOIP2013】火车运输 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的
情况下,最多能运多重的货物。

输入格式

输入文件第一行有两个用一个空格隔开的整数 【CODEVS 3287】【NOIP2013】火车运输, 表示 【CODEVS 3287】【NOIP2013】火车运输 国有 【CODEVS 3287】【NOIP2013】火车运输 座城市和 【CODEVS 3287】【NOIP2013】火车运输 条道
路。
接下来 【CODEVS 3287】【NOIP2013】火车运输 行每行 【CODEVS 3287】【NOIP2013】火车运输 个整数 【CODEVS 3287】【NOIP2013】火车运输,每两个整数之间用一个空格隔开,表示从 【CODEVS 3287】【NOIP2013】火车运输 号城市
【CODEVS 3287】【NOIP2013】火车运输 号城市有一条限重为 【CODEVS 3287】【NOIP2013】火车运输 的道路。注意: 【CODEVS 3287】【NOIP2013】火车运输 不等于 【CODEVS 3287】【NOIP2013】火车运输,两座城市之间可能有多条道路。
接下来一行有一个整数 【CODEVS 3287】【NOIP2013】火车运输,表示有 【CODEVS 3287】【NOIP2013】火车运输 辆货车需要运货。
接下来 【CODEVS 3287】【NOIP2013】火车运输 行,每行两个整数 【CODEVS 3287】【NOIP2013】火车运输【CODEVS 3287】【NOIP2013】火车运输,之间用一个空格隔开,表示一辆货车需要从 【CODEVS 3287】【NOIP2013】火车运输 城市
运输货物到 【CODEVS 3287】【NOIP2013】火车运输城市,注意:【CODEVS 3287】【NOIP2013】火车运输 不等于 【CODEVS 3287】【NOIP2013】火车运输

输出格式

输出共有 【CODEVS 3287】【NOIP2013】火车运输 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货
车不能到达目的地,输出 【CODEVS 3287】【NOIP2013】火车运输

输入样例

4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3

输出样例

3
-1
3

数据范围

【CODEVS 3287】【NOIP2013】火车运输

题解

可以证明最优路径一定在最大生成树(森林)上,于是题目便转化为,询问森林中两点路径上边权最小值,连通性用并查集判断即可。

对于一棵树上的一次询问,可以用倍增的方法解决。

【CODEVS 3287】【NOIP2013】火车运输 表示点 【CODEVS 3287】【NOIP2013】火车运输 向上 【CODEVS 3287】【NOIP2013】火车运输 步到达的结点                            【CODEVS 3287】【NOIP2013】火车运输

【CODEVS 3287】【NOIP2013】火车运输 表示点 【CODEVS 3287】【NOIP2013】火车运输 向上 【CODEVS 3287】【NOIP2013】火车运输 步的路径中的边权最小值 【CODEVS 3287】【NOIP2013】火车运输

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#define N 10005
#define M 50005
#define depth 21
using namespace std;

int n,m,q,cnt,tot,ans;
int f[N],last[N],dep[N];
int anc[N][22],g[N][22];
struct hh
{int to,next,w;}e[M<<1];
struct hhh
{int l,r,w;}line[M<<1];
bool cmp(hhh a,hhh b){return a.w>b.w;}
int read()
{
    int ret=0;char c=getchar();
    while(!isdigit(c))c=getchar();
    while(isdigit(c)){ret=(ret<<1)+(ret<<3)+c-'0';c=getchar();}
    return ret;
}
void add(int a,int b,int w)
{
    e[++tot].to=b;
    e[tot].next=last[a];
    e[tot].w=w;
    last[a]=tot;
}
void bfs(int root)
{
    int i,j,now;
    stack<int> s;
    s.push(root);dep[root]=1;
    for(i=0;i<depth;i++) anc[root][i]=root;
    while(!s.empty())
    {
        now=s.top();s.pop();    
        if(now!=root)
            for(i=1;i<depth;i++)
            {
                anc[now][i]=anc[anc[now][i-1]][i-1];
                g[now][i]=min(g[now][i-1],g[anc[now][i-1]][i-1]);
            }                
        for(i=last[now];i;i=e[i].next)
            if(!dep[e[i].to])
            {
                anc[e[i].to][0]=now;
                dep[e[i].to]=dep[now]+1;
                g[e[i].to][0]=e[i].w;
                s.push(e[i].to);
            }
    }
}
void swim(int& x,int h)
{
    int i;
    for(i=0;h;i++)
    {
        if(h&1) x=anc[x][i];
        h>>=1;
    }
}
int getlca(int x,int y)
{
    int i,j;
    if(dep[x]<dep[y]) swap(x,y);
    swim(x,dep[x]-dep[y]);
    if(x==y) return x;
    while(true)
    {
        for(i=0;anc[x][i]!=anc[y][i];i++);
        if(!i) return anc[x][0];
        x=anc[x][i-1];y=anc[y][i-1];
    }
}
int query(int x,int y)
{
    int i,ret=9999999,h;
    h=dep[y]-dep[x];
    for(i=depth;i>=0;i--)
        if((1<<i)<=h)
        {
            h-=(1<<i);
            ret=min(ret,g[y][i]);
            y=anc[y][i];
        }
    return ret;
}
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
int main()
{
    int i,j,u,v,w,fx,fy,lca;
    n=read();m=read();
    for(i=1;i<=m;i++)
        line[i].l=read(),line[i].r=read(),line[i].w=read();
    sort(line+1,line+1+m,cmp);
    for(i=1;i<=n;i++) f[i]=i;
    for(i=1;i<=m;i++)
    {
        u=line[i].l;v=line[i].r;w=line[i].w;
        fx=find(u);fy=find(v);
        if(fx!=fy)
        {
            f[fx]=fy;cnt++;
            add(u,v,w);add(v,u,w);
            if(cnt==n-1) break;
        }
    }
    for(i=1;i<=n;i++)
        for(j=0;j<depth;j++)
            g[i][j]=9999999;
    bfs(1);
    q=read();
    for(i=1;i<=q;i++)
    {
        u=read();v=read();
        if(find(u)!=find(v)){puts("-1");continue;}
        lca=getlca(u,v);
        ans=min(query(lca,u),query(lca,v));
        printf("%d
",ans);
    }
    return 0;
}