ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

J [NOIP2013]货车运输 lca 最大生成树 点和点之间所有路径最小值的最大值

2022-08-31 17:33:35  阅读:213  来源: 互联网

标签:NOIP2013 min int 货车运输 点和点 re 000 dp dis


 链接:https://ac.nowcoder.com/acm/problem/16527
来源:牛客网

题目描述

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

输入描述:

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

接下来 m 行每行 3 个整数 x, y, z ,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意: x 不等于 y ,两座城市之间可能有多条道路 。 接下来一行有一个整数 q,表示有 q 辆货车需要运货。 接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y

 

输出描述:

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

输入

复制
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3

输出

复制
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 。

分析

题意:路径上的最小权值最大

容易想到floyd但是时间复杂度不够

只要用kruskal跑一边找出 n - 1条边的最大生成树,就能找到点和点之间所有路径的最大路径

然后用lca求一下每两个点之间的最小权值就可以了

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long int ll;
#define inf 0x3f3f3f3f
const int mod=1e9+7;
#define mst(a) memset(a,0,sizeof(a))
int d[4][2]={{1,0},{0,-1},{0,1},{-1,0}};
const double eps = 1e-3;
const int N=1e5+7;
struct Edge{
    int next, w;
};

vector<Edge>edge[N];
ll dis[N][25];
int depth[N];
int dp[N][25];

struct node{
    int u,v,w;
}a[N];

class Dsu
{
public:
    int pre[N];
    
    Dsu(int n){
        for(int i=1; i<=n; i++){
            pre[i] = i;
        }
    }
    
    int find(int x){
        return x == pre[x] ? x : pre[x] = find(pre[x]);
    }
    
    void merge(int x, int y){
        int fx = find(x), fy = find(y);
        if(fx == fy){
            return;
        }
        pre[fx] = fy;
    }
};

class LCA
{
    bool vis[N];
public:
    void dfs(int u){
        for(int i=1; (1<<i) <= depth[u]; i++){
            dp[u][i] = dp[dp[u][i - 1]][i - 1];
            dis[u][i] = min(dis[u][i - 1], dis[dp[u][i - 1]][i - 1]);
        }
        vis[u] = true;
        for(auto it:edge[u]){
            if(vis[it.next]) continue;
            dis[it.next][0] = it.w;
            depth[it.next] = depth[u] + 1;
            dp[it.next][0] = u;
            dfs(it.next);
        }
    }
    
    LCA(int n){
        mst(vis);
        memset(dis,inf,sizeof(dis));
        for(int i = 1; i <= n; i++){
            if(!vis[i]){
                dp[i][0] = -1;
                depth[i] = 1;
                dfs(i);
            }
        }
    };
    
    ll getLCA(int x, int y){
        if(depth[x] < depth[y]) swap(x, y);
        ll re=inf;
        int t=depth[x] - depth[y];
        for(int i=0;t;i++,t>>=1){
            if(t & 1){
                re = min(re, dis[x][i]);
                x = dp[x][i];
            }
        }
        if(x == y) return re;
        for(int i = 20; i >= 0; i--){
            if(dp[x][i] != dp[y][i]){
                re = min(re, dis[x][i]);
                re = min(re, dis[y][i]);
                x = dp[x][i];
                y = dp[y][i];
            }
        }
        return min(re, min(dis[x][0], dis[y][0]));
    }
};

inline Dsu Kruskal(int n, int m){
    sort(a + 1, a + m + 1, 
         [](node x, node y)->bool{
             return x.w > y.w;
         });
    Dsu t(n);
    for(int i=1; i<=m; i++){
        int u = t.find(a[i].u), v = t.find(a[i].v);
        if(u != v){
            t.merge(u, v);
            edge[a[i].u].push_back({a[i].v,a[i].w});
            edge[a[i].v].push_back({a[i].u,a[i].w});
        }
    }
    return t;
}

int main()
{
    int n, m;
    scanf("%d%d",&n, &m);
    for(int i=1; i<=m; i++){
        scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].w);
    }
    Dsu t = Kruskal(n,m);
    LCA lca(n);
    int q;
    scanf("%d",&q);
    while(q--){
        int x, y;
        scanf("%d%d",&x, &y);
        if(t.find(x) != t.find(y)){
            printf("-1\n");
        }else{
            printf("%lld\n",lca.getLCA(x, y));
        }
    }
    return 0;
}

 

标签:NOIP2013,min,int,货车运输,点和点,re,000,dp,dis
来源: https://www.cnblogs.com/er007/p/16643857.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有