noip2013 貨車運輸


P1967 貨車運輸

    • 406通過
    • 1.4K提交
  • 題目提供者該用戶不存在
  • 標簽圖論貪心2013NOIp提高組
  • 難度提高+/省選-

提交該題 討論 題解 記錄

最新討論

題目描述

A 國有 n 座城市,編號從 1 到 n,城市之間有 m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 q 輛貨車在運輸貨物, 司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。

輸入輸出格式

輸入格式:

 

輸入文件名為 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。

 

輸入輸出樣例

輸入樣例#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,000。

分析:這道題目就是求x到y的路徑上最小值最大的權值,固定的方法就是最大生成樹,當然如果是最大值最小,那么就是最小生成樹.怎么求最大生成樹呢?首先要是一棵樹,兩個點之間只有唯一的路徑,怎么判斷兩個點是否連通呢?並查集!怎么要滿足“最大”呢?排序!那么就先從大到小排序,把不在一個連通塊的兩個點連起來就可以了.那么就要求最小值最大,怎么求呢?可以知道這條唯一的路徑是兩個點到它們的lca的和,怎么求lca呢?倍增!首先一次dfs記錄出f[i][j],g[i][j],即第i個節點的第2^j個祖先和所求的最小值最大的結果.同時記錄下每個節點的深度,注意,這個深度是越大越往下.為了求lca(a,b),假設a的深度比b的深度大,那么把a往上移,直到深度相同,同時更新ans,這個時候如果a==b了,那么就返回,然后再讓兩個點同時上移,如果兩個點上移之后相等了,因為我們是從大到小枚舉2^j的,所以求出的點可能在lca上面,所以當兩個祖先不是相同的才跳.那么跳到最后就跳到了lca的下一層,往上再跳一個就可以了.每次跳都要更新ans.

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 10010, maxm = 50010;

int n, m, q, fa[maxn], head[maxn], cnt, h[maxn], f[maxn][20], g[maxn][20], ans = 1000000000;
bool vis[maxn];

struct node
{
    int x, y, z;
}a[maxm];

struct node2
{
    int nextt, to, w;
}e[maxn * 2];

bool cmp(node a1, node b)
{
    return a1.z > b.z;
}

void dfs(int u, int depth)
{
    vis[u] = true;
    h[u] = depth;
    for (int i = head[u]; i; i = e[i].nextt)
        if (!vis[e[i].to])
        {
        f[e[i].to][0] = u;
        g[e[i].to][0] = e[i].w;
        dfs(e[i].to, depth + 1);
        }
    return;
}

int find(int x)
{
    if (fa[x] != x)
        fa[x] = find(fa[x]);
    return fa[x];
}

void add(int p, int q, int v)
{
    e[++cnt].to = q;
    e[cnt].nextt = head[p];
    head[p] = cnt;
    e[cnt].w = v;
}

void kruskal()
{
    sort(a + 1, a + 1 + m, cmp);
    for (int i = 1; i <= n; i++)
        fa[i] = i;
    for (int i = 1; i <= m; i++)
    {
        int fx = find(a[i].x), fy = find(a[i].y);
        if (fx == fy)
            continue;
        fa[fx] = fy;
        add(a[i].x, a[i].y, a[i].z);
        add(a[i].y, a[i].x, a[i].z);
    }
}

int lca(int a1, int b1)
{
    ans = 1000000000;
    if (a1 == b1)
        return 0;
    if (h[a1] < h[b1])
        swap(a1, b1);
    int k = int(log2(h[a1]));
    for (int i = k; i >= 0; i--)
        if (h[a1] - (1 << i) >= h[b1])
        {
        ans = min(ans, g[a1][i]);
        a1 = f[a1][i];
        }
    if (a1 == b1)
        return ans;
    for (int i = k; i >= 0; i--)
        if (f[a1][i] && f[a1][i] != f[b1][i])
        {
        ans = min(ans, min(g[a1][i], g[b1][i]));
        a1 = f[a1][i];
        b1 = f[b1][i];
        }
    ans = min(ans, min(g[a1][0], g[b1][0]));
    return ans;
}

int main()
{
    memset(vis, false, sizeof(vis));
    memset(head, 0, sizeof(head));
    memset(f, 0, sizeof(f));
    memset(g, 127, sizeof(g)); //INF
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++)
        scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].z);
    kruskal();
    scanf("%d", &q);
    for (int i = 1; i <= n; i++)
        if (!vis[i])
        dfs(i, 1);
    for (int j = 1; (1 << j) <= n; j++)
        for (int i = 1; i <= n; i++)
            if (f[i][j - 1])
            {
        f[i][j] = f[f[i][j - 1]][j - 1];
        g[i][j] = min(g[i][j - 1], g[f[i][j - 1]][j - 1]);
            }
    for (int i = 1; i <= q; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        if (find(x) != find(y))
            printf("-1\n");
        else
            printf("%d\n", lca(x, y));
    }

    return 0;
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM