zoukankan      html  css  js  c++  java
  • 「NOIP2013」「LuoguP1967」货车运输(最大生成树 倍增 LCA

    题目描述

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

    输入输出格式

    输入格式:

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

    接下来 mm行每行33个整数 x, y, zx,y,z,每两个整数之间用一个空格隔开,表示从 xx号城市到yy号城市有一条限重为 zz 的道路。注意: xx 不等于 yy,两座城市之间可能有多条道路 。

    接下来一行有一个整数 q,表示有 q 辆货车需要运货。

    接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y 。

    输出格式:

    共有 qq 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-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%的数据,0 < n < 1,000,0 < m < 10,000,0 < q< 1,0000<n<1,000,0<m<10,000,0<q<1,000;

    对于 60\%60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q< 1,0000<n<1,000,0<m<50,000,0<q<1,000;

    对于 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,0z100,000。

    题解

    跑个最大生成树,然后对于每次询问在最大生成树上走树上路径,就能保证运的最重。

    所以对于每次询问,如果两点在一个联通块上,输出树上路径的最小边权值,否则输出-1就行了。

    实现过程很像「LuoguP4180」 【模板】严格次小生成树[BJWC2010](倍增 LCA Kruscal,但是要好码一丢丢。

      1 /*
      2 qwerta 
      3 P1967 货车运输 Accepted 
      4 100
      5 代码 C++,1.84KB
      6 提交时间 2018-11-02 22:17:58
      7 耗时/内存 453ms, 2548KB
      8 */
      9 #include<algorithm>
     10 #include<iostream>
     11 #include<cstdio>
     12 #include<cmath>
     13 using namespace std;
     14 const int MAXN=10000+3,MAXM=50000+3;
     15 struct emm{
     16     int x,y,l;
     17 }b[MAXM];
     18 bool cmpb(emm qaq,emm qwq){
     19     return qaq.l>qwq.l;
     20 }
     21 int fa[MAXN];
     22 int fifa(int x)
     23 {
     24     if(fa[x]==x)return x;
     25     return fa[x]=fifa(fa[x]);
     26 }
     27 struct ahh{
     28     int e,f,l;
     29 }a[2*MAXN];
     30 int h[MAXN];
     31 int tot=0;
     32 void con(int x,int y,int l)
     33 {
     34     a[++tot].f=h[x];
     35     h[x]=tot;
     36     a[tot].e=y;
     37     a[tot].l=l;
     38     a[++tot].f=h[y];
     39     h[y]=tot;
     40     a[tot].e=x;
     41     a[tot].l=l;
     42     return;
     43 }
     44 int d[MAXN];
     45 int f[MAXN][13];
     46 int mi[MAXN][13];
     47 void dfs(int x)
     48 {
     49     for(int i=h[x];i;i=a[i].f)
     50     if(!d[a[i].e])
     51     {
     52         d[a[i].e]=d[x]+1;
     53         f[a[i].e][0]=x;
     54         mi[a[i].e][0]=a[i].l;
     55         dfs(a[i].e);
     56     }
     57     return;
     58 }
     59 bool sf[MAXN];
     60 int main()
     61 {
     62     //freopen("a.in","r",stdin);
     63     int n,m;
     64     scanf("%d%d",&n,&m);
     65     for(int i=1;i<=m;++i)
     66     {
     67         scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].l);
     68     }
     69     sort(b+1,b+m+1,cmpb);
     70     for(int i=1;i<=n;++i)
     71         fa[i]=i;
     72     int k=n-1,i=0;
     73     while(k&&i<=m)
     74     {
     75         i++;
     76         int u=fifa(b[i].x),v=fifa(b[i].y);
     77         if(u!=v)
     78         {
     79             //cout<<i<<" "<<b[i].x<<" "<<b[i].y<<" "<<b[i].l<<endl;
     80             fa[u]=v;
     81             con(b[i].x,b[i].y,b[i].l);
     82             k--;
     83         }
     84     }
     85     for(int s=1;s<=n;++s)
     86     if(!sf[fifa(s)])
     87     {
     88         sf[fifa(s)]=1;
     89         d[s]=1;
     90         dfs(s);
     91     }
     92     for(int j=1;j<=10;++j)
     93     for(int i=1;i<=n;++i)
     94     {
     95         f[i][j]=f[f[i][j-1]][j-1];
     96         mi[i][j]=min(mi[i][j-1],mi[f[i][j-1]][j-1]);
     97     }
     98     int q;
     99     scanf("%d",&q);
    100     while(q--)
    101     {
    102         int u,v;
    103         scanf("%d%d",&u,&v);
    104         if(fifa(u)!=fifa(v)){printf("-1
    ");continue;}
    105         if(d[u]<d[v])swap(u,v);
    106         int ans=1e6+2333;
    107         for(int j=10;j>=0;--j)
    108         if(d[u]-d[v]>=(1<<j))
    109         {
    110             ans=min(ans,mi[u][j]);
    111             u=f[u][j];
    112         }
    113         if(u==v){printf("%d
    ",ans);continue;}
    114         for(int j=10;j>=0;--j)
    115         if(f[u][j]!=f[v][j])
    116         {
    117             ans=min(ans,mi[u][j]);
    118             u=f[u][j];
    119             ans=min(ans,mi[v][j]);
    120             v=f[v][j];
    121         }
    122         ans=min(ans,mi[u][0]);
    123         ans=min(ans,mi[v][0]);
    124         printf("%d
    ",ans);
    125     }
    126     return 0;
    127 }
  • 相关阅读:
    ci中使用mail类
    简单php发送邮件
    Firefox 中出现的 “Network Protocol Error”怎么办
    让linux启动更快的方法
    小米盒子3代码公布了,你要刷机吗?
    毕业季,我的Linux求职之路
    菜鸟学习计划浅谈之Linux系统
    细述:nginx http内核模块提供的变量和解释
    Linux使用百度云
    网工的Linux系统学习历程
  • 原文地址:https://www.cnblogs.com/qwerta/p/9901133.html
Copyright © 2011-2022 走看看