樹上倍增

題目描述

A 國有 nn 座城市,編號從 11 到 nn,城市之間有 mm 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。

現在有 qq 輛貨車在運輸貨物, 司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。

輸入格式

第一行有兩個用一個空格隔開的整數 n,mn,m,表示 AA 國有 nn 座城市和 mm 條道路。

接下來 mm 行每行三個整數 x, y, zx,y,z,每兩個整數之間用一個空格隔開,表示從 xx 號城市到 yy 號城市有一條限重爲 zz 的道路。
注意: x \neq yx​=y,兩座城市之間可能有多條道路 。

接下來一行有一個整數 qq,表示有 qq 輛貨車需要運貨。

接下來 qq 行,每行兩個整數 x,yx,y,之間用一個空格隔開,表示一輛貨車需要從 xx 城市運輸貨物到 yy 城市,保證 x \neq yx​=y

輸出格式

共有 qq 行,每行一個整數,表示對於每一輛貨車,它的最大載重是多少。
如果貨車不能到達目的地,輸出 -1−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\%30% 的數據,1 \le n < 10001≤n<1000,1 \le m < 10,0001≤m<10,000,1\le q< 10001≤q<1000;

對於 60\%60% 的數據,1 \le n < 10001≤n<1000,1 \le m < 5\times 10^41≤m<5×104,1 \le q< 10001≤q<1000;

對於 100\%100% 的數據,1 \le n < 10^41≤n<104,1 \le m < 5\times 10^41≤m<5×104,1 \le q< 3\times 10^41≤q<3×104,0 \le z \le 10^50≤z≤105。

這個題目我沒有看板子ac的。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 10010;
const int inf = 0x3f3f3f3f;
struct node
{
    int x, y, z;
} N[maxn * 5 + 10];
vector<pair<int, int> > V[maxn];
int f[maxn], anc[maxn][(int)log2(maxn)], dis[maxn][(int)log2(maxn)], Dep[maxn],vis[maxn];
void init(int n)
{
    for (int i = 0; i <= n; i++)
        f[i] = i;
    memset(anc, 0, sizeof(anc));
    memset(dis, inf, sizeof(dis));
    memset(Dep, 0, sizeof(Dep));
    memset(vis,0,sizeof(vis));
}
int Find(int x)
{
    return f[x] == x ? x : (f[x] = Find(f[x]));
}
void Merge(int x, int y)
{
    int X = Find(x);
    int Y = Find(y);
    f[X] = Y;
    return;
}
void dfs(int x, int dep)
{
    vis[x]=1;
    for(auto it =V[x].begin(); it!=V[x].end(); it++)
    {
        if(vis[(*it).first])
            continue;
        anc[(*it).first][0] = x;
        dis[(*it).first][0] = (*it).second;
        Dep[(*it).first] = dep+1;
        for (int i = 1; i <=(int)log2(dep+1); i++)
        {
            anc[(*it).first][i] = anc[anc[(*it).first][i-1]][i - 1];
            dis[(*it).first][i] = min(dis[(*it).first][i - 1], dis[anc[(*it).first][i-1]][i - 1]);
        }
        dfs((*it).first, dep + 1);
    }
    return;
}
int solve(int x, int y)
{
    if (Find(x) != Find(y))
        return -1;
    int ans = inf;
    if (Dep[x] < Dep[y])
        swap(x, y);
    int C = Dep[x] - Dep[y];
    for (int i = 0; i <=(int)log2(C); i++)
    {
        if (((1 << i) & C))
        {
            ans = min(ans, dis[x][i]);
            x = anc[x][i];
        }
    }
    if (x != y)
        for (int i =(int)(log2(Dep[x])); i >= 0; i--)
        {
            if(i==0)
            {
                ans = min(min(ans, dis[x][i]), dis[y][i]);
                x = anc[x][i];
                y = anc[y][i];
            }
            else
            {
                if (anc[x][i]!=anc[y][i])
                {
                    ans = min(min(ans, dis[x][i]), dis[y][i]);
                    x = anc[x][i];
                    y = anc[y][i];
                }
            }
        }
    if(x!=y)
        ans= min(ans,min(dis[x][0],dis[y][0]));
    return ans;
}
int main()
{
    int n, m, q;
    cin >> n >> m;
    init(n);
    for (int i = 0; i < m; i++)
    {
        cin >> N[i].x >> N[i].y >> N[i].z;
    }
    sort(N, N + m, [=](node a, node b)
    {
        return a.z > b.z ;
    });
    for (int i = 0; i < m; i++)
    {
        if (Find(N[i].x) != Find(N[i].y))
        {
            Merge(N[i].x, N[i].y);
            V[N[i].x].push_back(make_pair(N[i].y, N[i].z));
            V[N[i].y].push_back(make_pair(N[i].x, N[i].z));
        }
    }
    for (int i = 1; i <= n; i++)
    {
        if (vis[i])
            continue;
        dfs(i, 0);
    }
    int x, y;
    cin>>q;
    while (q--)
    {
        cin >> x >> y;
        cout << solve(x, y) << endl;
    }
}
/*
5 6
1 2 1
2 3 2
3 6 3
1 4 1
4 5 2
5 7 3
100
3 5
6 7

*/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章