货车运输

  题目描述 Description
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
  输入输出格式 Input/output
输入格式:
输入文件名为 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。
  输入输出样例 Sample input/output
样例测试点#1
输入样例:  在线IDE
输出样例:
  说明 description
对于 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。


嗯。。。一开始没对拍WA了一次,比赛要注意了!
就是最大生成树+LCA啦
注意查询的时候一定保持x!=y!!!

#include<iostream>  
#include<cstdio>  
#include<cmath>  
#include<algorithm>  
#include<vector>  
#include<queue>  
using namespace std;  
  
const int maxn = 1e4 + 10;  
  
struct E{  
    int x,y,z;  
    bool operator < (const E &b) const {  
        return z > b.z;    
    }  
}edgs[5*maxn];  
  
struct e{int to,w;};  
  
int anc[maxn][20],mincost[maxn][20],L[maxn],sccno[maxn],cur;  
int n,m,p,father[maxn],i,j;  
  
vector <e> v[maxn];  
queue <int> q;  
  
int fa(int k) {return k == father[k]?k:father[k] = fa(father[k]);}  
  
void bfs(int root) {  
    ++cur;  
    sccno[root] = cur;  
    q.push(root);  
    L[root] = 0;  
    while (!q.empty()) {  
        int k = q.front();  
        q.pop();  
        for (int l = 0; l < v[k].size(); l++) {  
            int to = v[k][l].to;  
            int w = v[k][l].w;  
            if (sccno[to] != cur) {  
                sccno[to] = cur;  
                anc[to][0] = k;  
                mincost[to][0] = w;  
                L[to] = L[k]+1;  
                q.push(to);  
                for (j = 1; L[to] - (1<<j) >= 0; j++) {  
                    int F = anc[to][j-1];  
                    anc[to][j] = anc[F][j-1];  
                    mincost[to][j] = min(mincost[to][j-1],mincost[F][j-1]);  
                }  
            }  
        }  
    }  
}  
  
int query(int x,int y)  
{  
    if (L[x] < L[y]) swap(x,y);  
    int log = 0;  
    while (L[x] - (1<<log) >= 0) log++; log--;  
    int ret = 1E9;  
    for (j = log; j >= 0; j--)  
        if (L[x] == L[y]) break;  
        else {  
            if (L[x] - (1<<j) >= L[y]) {  
                ret = min(ret,mincost[x][j]);  
                x = anc[x][j];  
            }  
        }  
    if (x == y) return ret;  
    for (j = log; j >= 0; j--)  
        if (L[x] - (1<<j) >= 0 && anc[x][j] != anc[y][j]) {  
            ret = min(ret,mincost[x][j]);  
            ret = min(ret,mincost[y][j]);  
            x = anc[x][j];  
            y = anc[y][j];  
        }  
    ret = min(ret,mincost[x][0]);  
    ret = min(ret,mincost[y][0]);  
    return ret;  
}  
  
int main()  
{  
      
    cin >> n >> m;  
    for (i = 1; i <= n; i++) father[i] = i;  
    for (i = 0; i < m; i++) scanf("%d%d%d",&edgs[i].x,&edgs[i].y,&edgs[i].z);  
    sort (edgs,edgs + m);  
    for (i = 0; i < m; i++) {  
        int x = edgs[i].x;  
        int y = edgs[i].y;  
        int fx = fa(x);  
        int fy = fa(y);  
        if (fx != fy) {  
            father[fx] = fy;  
            v[x].push_back((e){y,edgs[i].z});  
            v[y].push_back((e){x,edgs[i].z});  
        }  
    }  
      
    for (i = 1; i <= n; i++) if (!sccno[i]) bfs(i);  
      
    cin >> p;  
    while (p--) {  
        int x,y;  
        scanf("%d%d",&x,&y);  
        if (sccno[x] != sccno[y]) {  
            printf("-1\n");  
            continue;  
        }  
        printf("%d\n",query(x,y));  
    }  
    return 0;   
}  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值