• TZOJ 4848 货车运输(最大生成树+倍增lca)


    描述

    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。

    样例输入

    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。

    题意

    如上

    题解

    要使路径上的最小值尽可能大,跑一个最大生成树

    然后在查询树上路径最小值的时候,可以跑一个倍增lca

    查询u,v的最小值的时候,先找到u,v的公共祖先p,再求min(up的最小值,vp的最小值)

    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 
      4 const int maxn=10005;
      5 const int maxm=50005;
      6 int deep[maxn],fa[maxn][20],dis[maxn][20],lg[maxn],vis[maxn],f[maxn],n,m;
      7 vector< pair<int,int> >G[maxn];
      8 struct edge
      9 {
     10     int u,v,w;
     11     bool operator<(const edge &D)const{
     12         return w>D.w;
     13     }
     14 }edges[maxm];
     15 void dfs(int u)
     16 {
     17     vis[u]=1;
     18     for(auto X:G[u])
     19     {
     20         int v=X.first;
     21         int w=X.second;
     22         if(vis[v])continue;
     23         fa[v][0]=u;
     24         dis[v][0]=w;
     25         deep[v]=deep[u]+1;
     26         dfs(v);
     27     }   
     28 }
     29 void RNQ()
     30 {
     31     for(int j=1;(1<<j)<=n;j++)
     32         for(int i=1;i<=n;i++)
     33             fa[i][j]=fa[fa[i][j-1]][j-1],
     34             dis[i][j]=min(dis[i][j-1],dis[fa[i][j-1]][j-1]);
     35 }
     36 int lca(int x,int y)
     37 {
     38     if(deep[x]<deep[y])swap(x,y);
     39     while(deep[x]>deep[y])x=fa[x][lg[deep[x]-deep[y]]-1];
     40     if(x==y)return x;
     41     for(int k=lg[deep[x]];k>=0;k--)
     42         if(fa[x][k]!=fa[y][k])
     43             x=fa[x][k],y=fa[y][k];
     44     return fa[x][0];
     45 }
     46 int find(int x)
     47 {
     48     return f[x]==x?x:f[x]=find(f[x]);
     49 }
     50 int query(int x,int y)
     51 {
     52     int ans=0x3f3f3f3f,t=deep[x]-deep[y];
     53     for(int i=0;i<=16;i++)
     54         if(t&(1<<i))
     55             ans=min(ans,dis[x][i]),
     56             x=fa[x][i];
     57     return ans;
     58 }
     59 void max_kruskal()
     60 {
     61     int cnt=0;
     62     sort(edges,edges+m);
     63     for(int i=0;i<m;i++)
     64     {
     65         int u=edges[i].u;
     66         int v=edges[i].v;
     67         int w=edges[i].w;
     68         int fu=find(u);
     69         int fv=find(v);
     70         if(fu!=fv)
     71         {
     72             G[u].push_back({v,w});
     73             G[v].push_back({u,w});
     74             f[fu]=fv;
     75             if(++cnt==n-1)break;
     76         }
     77     }
     78 }
     79 int main()
     80 {
     81     memset(dis,0x3f3f3f3f,sizeof dis);
     82     memset(vis,false,sizeof vis);
     83     int u,v,w,q;
     84     scanf("%d%d",&n,&m);
     85     for(int i=1;i<=n;i++)lg[i]=lg[i-1]+(1<<lg[i-1]==i),f[i]=i;
     86     for(int i=0;i<m;i++)
     87     {
     88         scanf("%d%d%d",&u,&v,&w);
     89         edges[i]={u,v,w};
     90     }
     91     max_kruskal();
     92     for(int i=1;i<=n;i++)if(!vis[i])dfs(i);
     93     RNQ();
     94     scanf("%d",&q);
     95     for(int i=0;i<q;i++)
     96     {
     97         scanf("%d%d",&u,&v);
     98         if(find(u)!=find(v))printf("-1
    ");
     99         else
    100         {
    101             int father=lca(u,v);
    102             printf("%d
    ",min(query(u,father),query(v,father)));
    103         }
    104     }
    105     return 0;
    106 }
  • 相关阅读:
    幂不等式
    一个对数级数的求和
    数列极限
    求幂级数的和函数
    证明整数为平方数
    java获取当前时间戳的方法
    《编程小白的第一本python入门书》笔记 二
    《编程小白的第一本python入门书》笔记 一
    python班级群中的问题记录-2016.12.30
    python班级群中的问题记录-2016.12.22
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/9671649.html
Copyright © 2020-2023  润新知