P1967 货车运输

题目描述

\(A\)国有\(n\)座城市,编号从\(1\)\(n\),城市之间有\(m\)条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有

\(q\)辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

输入格式

第一行有两个用一个空格隔开的整数\(n\),\(m\)表示 \(A\) 国有\(n\)座城市和\(m\)条道路。

接下来\(m\)行每行3个整数\(x\),\(y\),\(z\)每两个整数之间用一个空格隔开,表示从\(x\)号城市到\(y\)号城市有一条限重为z的道路。注意:\(x\)不等于 \(y\),两座城市之间可能有多条道路。

接下来一行有一个整数 \(q\),表示有 $q $辆货车需要运货。

接下来 \(q\) 行,每行两个整数 \(x\)\(y\),之间用一个空格隔开,表示一辆货车需要从 \(x\) 城市运输货物到\(y\)城市。
输出格式

共有\(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,0000;\)

代码

我们通过构造kruskal重构树,在树上查询两点lca的点权值,即为答案。

关于kruskal重构树操作

如将边权按降序排序
则LCA(u,v)的权值代表 原图 u到v路径上最大边权的最小值

如将边权按升序排序
则LCA(u,v)的权值代表 原图 u到v路径上最小边权的最大值

#include<bits/stdc++.h>
using namespace std;
const int maxn=200000+100,maxm=200000+100,md=20+5;
int head[maxn],val[maxn],f[maxn],dep[maxn],lg[maxn]; 
int ff[maxn][md];
int size=0,cnt=0;
struct tree
{
    int to,next;
}e[maxm<<1];
struct edge
{
    int u,v,val;
}E[maxm<<1];
int n,m;
void init()
{
    for(int i=1;i<=n;i++)
    f[i]=i;
}
int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}
void addedge(int u,int v)
{
    e[++size].to=v;e[size].next=head[u];head[u]=size;
}
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
bool cmp(const edge&a,const edge&b)
{
    return a.val>b.val;
}
void kruskal()
{
    for(int i=1;i<=m;i++)
    {
        int u=E[i].u,v=E[i].v;
        int fu=find(u),fv=find(v);
        if(fu!=fv)
        {
        cnt++;
        f[cnt]=f[fu]=f[fv]=cnt;
        val[cnt]=E[i].val;
        addedge(cnt,fu);addedge(fu,cnt);
        addedge(fv,cnt);addedge(cnt,fv);
        }

    }
}
void dfs(int u,int fa)
{
    dep[u]=dep[fa]+1;
    ff[u][0]=fa;
    for(int i=1;i<=lg[dep[u]];i++)
    ff[u][i]=ff[ff[u][i-1]][i-1];
    for(int i=head[u];i;i=e[i].next)
    {
        int to=e[i].to;
        if(to==fa)continue;
        dfs(to,u);
    }
}
int lca(int x,int y)
{
    if(dep[x]<dep[y])
    swap(x,y);
    while(dep[x]>dep[y])
    x=ff[x][lg[dep[x]-dep[y]]];
    if(x==y)
    return x;
    for(int i=lg[dep[x]];i>=0;i--)
    if(ff[x][i]!=ff[y][i])x=ff[x][i],y=ff[y][i];
    return ff[x][0];
}
int main()
{
    n=read(),m=read();cnt=n;
    init();
    for(int i=1;i<=m;i++)
    E[i].u=read(),E[i].v=read(),E[i].val=read();
    sort(E+1,E+1+m,cmp);
    kruskal();
    for(int i=1;i<=n;i++)
    lg[i]=lg[i-1]+(1<<(lg[i-1]+1)==i);
    for(int i=1;i<=cnt;i++)
    if(!dep[i])
    dfs(find(i),0); 
    int k=read();
    for(int i=1;i<=k;i++)
    {
        int x=read(),y=read();
        if(find(x)!=find(y))printf("-1\n");
        else printf("%d\n",val[lca(x,y)]);
    }
    return 0;
}
posted @ 2019-04-19 09:38  DriverBen  阅读(85)  评论(0编辑  收藏  举报