zoukankan      html  css  js  c++  java
  • [Noip2013] 货车运输

    题目描述

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

    输入输出格式

    输入格式:

    第一行有两个用一个空格隔开的整数n,m n,mn,m,表示 AAA 国有n nn 座城市和 mmm 条道路。

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

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

    接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y

    输出格式:

    共有 qqq 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出−1-11。

    输入输出样例

    输入样例#1: 复制
    4 3
    1 2 4
    2 3 3
    3 1 1
    3
    1 3
    1 4
    1 3
    输出样例#1: 复制
    3
    -1
    3

    说明

    对于 30%30\%30%的数据,0<n<1,000,0<m<10,000,0<q<1,0000 < n < 1,000,0 < m < 10,000,0 < q< 1,0000<n<1,000,0<m<10,000,0<q<1,000;

    对于 60%60\%60%的数据,0<n<1,000,0<m<50,000,0<q<1,0000 < n < 1,000,0 < m < 50,000,0 < q< 1,0000<n<1,000,0<m<50,000,0<q<1,000;

    对于 100%100\%100%的数据,0<n<10,000,0<m<50,000,0<q<30,000,0≤z≤100,0000 < n < 10,000,0 < m < 50,000,0 < q< 30,000,0 ≤ z ≤ 100,0000<n<10,000,0<m<50,000,0<q<30,000,0z100,000。


    说实话这题很容易想到,像我这样的蒟蒻都能想到...

    显然有一些边是没有用的,我们只需要保证图联通就行了,所以自然而然的想到生成树。

    所以求一遍最大生成树,然后后面的直接类似倍增找LCA一样的写就行了,十分简单。

    有个坑点,图不一定联通(废话,要不为什么输出-1)。

    然而数据有在一个联通块里的, 我预处理的时候只从1开始bfs,这样gg了,必须从所有联通块都处理一遍。

    轻松A掉。


    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <cstring>
    using namespace std;
    #define reg register 
    #define N 10005
    #define M 50005
    inline int read() {
        int res=0;char ch=getchar();
        while(!isdigit(ch))ch=getchar();
        while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
        return res;
    }
    
    int n, m;
    
    struct edge {
        int nxt, to, val, from;
    }ed[M*2];
    int cnt = 1, head[N];
    inline void add(int x, int y, int z)
    {
        ed[++cnt] = (edge){head[x], y, z, x};
        head[x] = cnt;
    }
    struct date {
        int x, y, id, val;
    }dat[M];
    inline bool cmp(date a, date b) {
        return a.val > b.val;
    }
    
    int fa[N];
    int Find(int x) {return fa[x]==x?x:fa[x]=Find(fa[x]);}
    
    int fu[N][20], mn[N][20];
    int dep[N];
    bool vis[N];
    
    inline void bfs(int cur)
    {
        queue <int> q;
        q.push(cur);
        dep[cur] = 1;
        vis[cur] = 1;
        while(!q.empty())
        {
            int x = q.front();q.pop();
            for (reg int i = head[x] ; i ; i = ed[i].nxt)
            {
                int to = ed[i].to;
                if (vis[to]) continue;
                vis[to] = 1;
                dep[to] = dep[x] + 1;
                fu[to][0] = x;
                mn[to][0] = ed[i].val;
                for (reg int j = 1 ; j <= 19 ; j ++)
                    fu[to][j] = fu[fu[to][j-1]][j-1], mn[to][j] = min(mn[to][j-1], mn[fu[to][j-1]][j-1]);
                q.push(to);
            }
        }
    }
    
    inline int solve(int x, int y)
    {
        int res = 1e9;
        if (dep[x] < dep[y]) swap(x, y);
        for (reg int i = 19 ; i >= 0 ; i --)
            if (dep[fu[x][i]] >= dep[y]) res = min(res, mn[x][i]), x = fu[x][i];
        if (x == y) return res;
        for (reg int i = 19 ; i >= 0 ; i --)
            if (fu[x][i] != fu[y][i]) res = min(res, min(mn[x][i], mn[y][i])), x = fu[x][i], y = fu[y][i];
        res = min(res, min(mn[x][0], mn[y][0]));
        return res;
    }
    
    int main()
    {
        n = read(), m = read();
        for (reg int i = 1 ; i <= m ; i ++)
        {
            int x = read(), y = read(), z = read();
            dat[i] = (date){x, y, i, z};
        }
        sort(dat + 1, dat + 1 + m, cmp);
        int k = 0;
        for (reg int i = 1 ; i <= n ; i ++) fa[i] = i;
        for (reg int i = 1 ; i <= m ; i ++)
        {
            int x = dat[i].x, y = dat[i].y;
            int fx = Find(x), fy = Find(y);
            if (fx == fy) continue;
            add(x, y, dat[i].val), add(y, x, dat[i].val);
            fa[fx] = fy;
            k++;
            if (k == n - 1) break;
        }
        memset(mn, 0x3f, sizeof mn);
        for (reg int i = 1 ; i <= n ; i ++)
            if (!vis[i]) bfs(i);
        int q = read();
        while(q--)
        {
            int x = read(), y = read();
            if (Find(x) != Find(y)) {puts("-1"); continue;}
            printf("%d
    ", solve(x, y));
        }
        return 0;
    }
  • 相关阅读:
    Struts2 Hello World
    Struts2入门(1)
    Struts2_day01
    Java Web Model2实战
    Oracle_day04
    SAP调用外部webservice接口
    通用清账程序
    服务器IDOC文件解析程序
    IDOC接口创建步骤
    SAP 本地发送IDOC
  • 原文地址:https://www.cnblogs.com/BriMon/p/9562879.html
Copyright © 2011-2022 走看看