zoukankan      html  css  js  c++  java
  • 洛谷 P1967 货车运输(克鲁斯卡尔重构树)

    题目描述

    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。

    题解:哦,这题是多么睿智啊,未来又可以多出一段梗了

    有一回对我说道,“你学过OI吗么?”我略略点一点头。他说,“学过OI,……我便考你一考。2013年提高组的D1T3,怎样写的?”

    我想,讨饭一样的人,也配考我么?便回过脸去,不再理会。

    孔乙己等了许久,很恳切的说道,“不能写罢?……我教给你,记着!这些题应该记着。将来打比赛的时候,贺题要用。”

    我暗想我和打模拟赛的水平还很远呢,而且我们比赛也从不将原题上账;又好笑,又不耐烦,懒懒的答他道,“谁要你教,不是最大生成树上跑跑倍增嘛?”

    孔乙己显出极高兴的样子,将两个指头的长指甲敲着键盘,点头说,“对呀对呀!……这道题有四样写法,你知道么?”

    我愈不耐烦了,努着嘴走远。孔乙己刚解了锁屏,想在电脑上写题,见我毫不热心,便又叹一口气,显出极惋惜的样子。

    反正原来的做法就是最大生成树上跑跑lca,过程中顺便记录一下答案(lca至少有四种求法,不接受任何反驳╭(╯^╰)╮)

    但我仔细一思索这题好像克鲁斯卡尔重构树也能做,大概做法就是建出一颗重构树以后输出询问两点之间的lca就可以啦

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    
    vector<int> g[60060];
    struct edge
    {
        int from,to,val;
    }e[50050];
    int fa[100010],n,m,cnt,v[100010],deep[100010],f[100010][18];
    
    int cmp(edge x,edge y)
    {
        return x.val>y.val;
    }
    
    int init()
    {
        for(int i=1;i<=100000;i++)
        {
            fa[i]=i;
        }
    }
    
    int find(int x)
    {
        if(fa[x]==x) return x;
        return fa[x]=find(fa[x]);
    }
    
    int union_(int x,int y,int val)
    {
        int fx=find(x);
        int fy=find(y);
        if(fx==fy) return 0;
        fa[fx]=fa[fy]=++cnt;
        g[fx].push_back(cnt);
        g[cnt].push_back(fx);
        g[fy].push_back(cnt);
        g[cnt].push_back(fy);
        v[cnt]=val;
    }
    
    int dfs(int now,int fat,int dep)
    {
        f[now][0]=fat;
        deep[now]=dep;
        for(int i=1;i<=17;i++) f[now][i]=f[f[now][i-1]][i-1];
        for(int i=0;i<g[now].size();i++)
        {
            if(g[now][i]==fat) continue;
            dfs(g[now][i],now,dep+1);
        }
    }
    
    int lca(int x,int y)
    {
        if(deep[x]<deep[y]) swap(x,y);
        for(int i=17;i>=0;i--) if(deep[f[x][i]]>=deep[y]) x=f[x][i];
        if(x==y) return x;
        for(int i=17;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    
    int main()
    {
        init();
        int from,to;
        scanf("%d%d",&n,&m);
        cnt=n;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].val);
        }
        sort(e+1,e+m+1,cmp);
        for(int i=1;i<=m;i++)
        {
            union_(e[i].from,e[i].to,e[i].val);
        }
        for(int i=1;i<=cnt;i++)
        {
            if(find(i)==i) dfs(i,0,1);
        }
        int ttt;
        scanf("%d",&ttt);
        while(ttt--)
        {
            scanf("%d%d",&from,&to);
            int anc=lca(from,to);
            if(anc) printf("%d
    ",v[anc]);
            else  puts("-1");
        }
    }
  • 相关阅读:
    UVa 1354 天平难题 (枚举二叉树)
    广西邀请赛总结
    UVa 12118 检查员的难题 (dfs判连通, 构造欧拉通路)
    UVA
    Uva 127 "Accordian" Patience (模拟)
    UVA 10539 Almost Prime Numbers( 素数因子)
    HDU 1272 小希的迷宫(并查集)
    HDU 1213 How Many Tables (并查集)
    POJ 2236 Wireless Network(并查集)
    HDU 1233 还是畅通工程 ( Kruskal或Prim)
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/9668548.html
Copyright © 2011-2022 走看看