M_sea

洛谷1967 货车运输
题目描述A 国有 n 座城市,编号从 1 到 n ,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称...
扫描右侧二维码阅读全文
04
2018/08

洛谷1967 货车运输

题目描述

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

传送门

算法

首先可以知道,边权小的边是没有用的。

那么先跑一遍最大生成树。

然后对于从i到j的路径,在树上可以看做从i到LCA再到j。

那么在倍增LCA的基础上再维护一个w数组,表示最小边权。

若i、j不在一个并查集内,那么输出-1即可。

细节见代码。

代码

#include <bits/stdc++.h>
#define re register
using namespace std;

inline int read() {
    int X=0,w=1; char c=getchar();
    while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
    while (c>='0'&&c<='9') X=(X<<3)+(X<<1)+c-'0',c=getchar();
    return X*w;
}

int root[100010];
inline void Init(int n) {
    for (re int i=1;i<=n;i++) root[i]=i;
}
inline int find(int x) {
    if (root[x]!=x) root[x]=find(root[x]);
    return root[x];
}
inline void merge(int a,int b) {
    a=find(a),b=find(b);
    if (a!=b) root[a]=b;
}

struct OgEdge {
    int u,v,w;
    bool operator <(const OgEdge& rhs) const {
        return w>rhs.w;
    }
};
OgEdge og_e[1000010];

struct Edge { int v,w,nxt; };
Edge e[200010];
int head[100010],cnt=0;

inline void addEdge(int u,int v,int w) {
//    printf("addEdge:%d %d %d\n",u,v,w);
    e[++cnt].v=v; e[cnt].w=w;
    e[cnt].nxt=head[u]; head[u]=cnt;
}

inline void Kruskal(int n,int m) {
    Init(n); sort(og_e+1,og_e+m+1);
    int s=0;
    for (re int i=1;i<=m;i++) {
        int x=og_e[i].u,y=og_e[i].v,w=og_e[i].w;
        if (find(x)==find(y)) continue;
        merge(x,y); s++;
        addEdge(x,y,w); addEdge(y,x,w);
        if (s==n-1) break;
    }
}

int f[100010][25];
int w[100010][25];
bool vis[100010];
int dep[100010];

inline void Dfs(int u) {
    vis[u]=1;
    for (re int i=head[u];i;i=e[i].nxt) {
        int v=e[i].v,W=e[i].w;
        if (!vis[v]) {
            dep[v]=dep[u]+1,f[v][0]=u,w[v][0]=W;
            Dfs(v);
        }
    }
}

inline int LCA(int a,int b) {
    int rt=2147483647;
    if (dep[a]<dep[b]) swap(a,b);
    for (re int i=21;~i;i--)
        if (dep[f[a][i]]>dep[b]) rt=min(rt,w[a][i]),a=f[a][i];
    if (dep[a]!=dep[b]) rt=min(rt,w[a][0]),a=f[a][0];
    for (re int i=21;~i;i--)
        if (f[a][i]!=f[b][i]) {
            rt=min(rt,min(w[a][i],w[b][i]));
            a=f[a][i],b=f[b][i];
        }
    if (a!=b) {
        rt=min(rt,min(w[a][0],w[b][0]));
        a=f[a][0],b=f[b][0];
    }
    return rt;
}

int main() {
    int n=read(),m=read();
    for (re int i=1;i<=m;i++) og_e[i].u=read(),og_e[i].v=read(),og_e[i].w=read();
    Kruskal(n,m);
    for (re int i=1;i<=n;i++)
        if (!vis[i]) { dep[i]=1; Dfs(i); f[i][0]=i,w[i][0]=2147483647; }
    for (re int i=1;i<=20;i++)
        for (re int j=1;j<=n;j++) {
            f[j][i]=f[f[j][i-1]][i-1];
            w[j][i]=min(w[j][i-1],w[f[j][i-1]][i-1]);
        }
    int q=read();
    for (re int i=1;i<=q;i++) {
        int x=read(),y=read();
        if (find(x)!=find(y)) printf("-1\n");
        else printf("%d\n",LCA(x,y));
    }
    return 0;
}
最后修改:2018 年 11 月 09 日 05 : 02 PM

发表评论