• codevs3287货车运输(最小生成树+LCA)


    3287 货车运输

     

    2013年NOIP全国联赛提高组

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 钻石 Diamond
     
     
    题目描述 Description

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

    输入描述 Input Description

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

    输出描述 Output Description

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

    样例输入 Sample Input

    4 3 
    1 2 4 
    2 3 3 
    3 1 1 
    3
    1 3 
    1 4 
    1 3

    样例输出 Sample Output

    3
    -1
    3

    数据范围及提示 Data Size & Hint

    对于 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。

    /*
    先跑最小生成树找到那些尽量大的边, 
    然后LCA维护两点间最小载重就好了。 
    至于-1的情况嘛 如果建完图后不在图里的自然就到不了了
    怎么算是不在图里呢 深度为0且不是树根(1)。 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define maxn 1000000
    
    using namespace std;
    int n,m,q,x,y,num,cnt,a,b,c,k,tmp;
    int deep[maxn],head[maxn],fa[maxn];
    int f[10010][21],dis[50010][21];
    struct node
    {
        int from;
        int to;
        int dis;
        int next;
    };
    node e[maxn*2],p[maxn*2];
    
    void add(int from,int to,int dis)
    {
        e[++num].from=from;
        e[num].to=to;
        e[num].dis=dis;
        e[num].next=head[from];
        head[from]=num;
    }
    
    bool cmp(node x,node y)
    {
        return x.dis>y.dis;
    }
    
    int find(int x)
    {
        if(x==fa[x])return x;
        else return fa[x]=find(fa[x]);
    }
    
    void Kruskal()
    {
        for(int i=1;i<=n;i++)
          fa[i]=i;
        sort(p+1,p+m+1,cmp);
        for(int i=1;i<=m;i++)
        {
            int r1=find(p[i].from);
            int r2=find(p[i].to);
            if(r1!=r2)
            {
                fa[r2]=r1;
                add(p[i].from,p[i].to,p[i].dis);
                add(p[i].to,p[i].from,p[i].dis);
                k++;
            }
            if(k==n-1) break;
        }
    }
    
    void DFS(int now,int from,int c,int Dis)
    {
        f[now][0]=from;deep[now]=c;
        dis[now][0]=Dis;
        for(int i=head[now];i;i=e[i].next)
        {
            if(e[i].to!=from)
              DFS(e[i].to,now,c+1,e[i].dis);
        }
    }
    
    void get_fa()
    {
        for(int j=1;j<=17;j++)
           for(int i=1;i<=n;i++)
           {
                   f[i][j]=f[f[i][j-1]][j-1];
                   dis[i][j]=min(dis[i][j],dis[f[i][j-1]][j-1]);
                   dis[i][j]=min(dis[i][j],dis[i][j-1]);
           }
    }
    
    int get_same(int a,int t)
    {
        for(int i=0;i<17;i++)
        {
            if(t&(1<<i))
              {
                  tmp=min(tmp,dis[a][i]);
                  a=f[a][i];
              }
        }
        return a;
    }
    
    int LCA_query(int a,int b)
    {
        if(a!=1&&deep[a]==0) return -1;
        if(b!=1&&deep[b]==0) return -1;
        tmp=0x3f3f3f3f;
        if(deep[a]<deep[b]) swap(a,b);
        a=get_same(a,deep[a]-deep[b]);
        if(a==b) return tmp;
        else
        {
            for(int i=17;i>=0;i--)
            {
                if(f[a][i]!=f[b][i])
                {
                    tmp=min(tmp,dis[a][i]);
                    tmp=min(tmp,dis[b][i]);
                    a=f[a][i];
                    b=f[b][i];
                }
            }
            tmp=min(tmp,dis[a][0]);
            tmp=min(tmp,dis[b][0]);
        }
        return tmp;
    }
    
    int main()
    {
        memset(dis,127/3,sizeof dis);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
          {
              scanf("%d%d%d",&a,&b,&c);
              p[i].from=a;
              p[i].to=b;
              p[i].dis=c;
          }
        Kruskal();
        DFS(1,1,0,0);dis[1][0]=0x3f3f3f3f;
        get_fa();
        scanf("%d",&q);
        for(int i=1;i<=q;i++)
        {
            scanf("%d%d",&x,&y);
            printf("%d
    ",LCA_query(x,y));
        }
        return 0;
    }
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    二分查找 java代码
    Failed at the bitcore-node@3.1.3 preinstall script './scripts/download' 设置linux proxy (代理)的方式
    github命令行实用操作
    H5无障碍旁白模式使用网页支持
    Vue框架搭建入门到熟悉
    解决IOS下返回不刷新的问题
    小程序—跳转 数据传递
    微信小程序——地图
    常用的正则判断
    JS 控制输入框输入表情emoji 显示在页面上
  • 原文地址:https://www.cnblogs.com/L-Memory/p/6363407.html
Copyright © 2020-2023  润新知