zoukankan      html  css  js  c++  java
  • 【NOIP2013】货车运输 最大生成树+LCA

    题目描述

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

    输入输出格式

    输入格式:

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

    接下来 m行每行3个整数 x,y,z,每两个整数之间用一个空格隔开,表示从 xx号城市到yy号城市有一条限重为 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
    输出样例#1:
    3
    -1
    3

    说明

    对于 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%的数据,0 < n < 1,000,0 < m < 50,000,0 < q< 1,0000<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,0000<n<10,000,0<m<50,000,0<q<30,000,0z100,000。

    --------------------------------------------------------------------

    这道题的思路就是先用最大生成树将图跑成一棵新树,然后在跑LCA的时候更新路上的最小值

    为什么呢,“我们可以发现有一些权值较小的边是不会被走过的。正如样例中的第三条边,就算有其他的很多条边,这条边无论如何也是不会被走过的。于是我们想到了可以将图中这样的边去掉,按照这个思路我们便想到了构造最大生成树,将其余的边去除。”(来自luogu的大佬

    然后我的关注点就变为了如何在LCA上记录最小值呢?

    在预处理每个点的父亲的时候 我们用一个相似的f[i][j]数组来记录i跳2^j时的最小边权

    注意:LCA在开数组的时候,maxn=20, 则p[N][maxn+5] (这个错查了2h....以后绝对不能再犯了

      1 #include<bits/stdc++.h>
      2 #define N 100010
      3 #define maxn 20
      4 #define INF 0x7f7f7f7f
      5 #define ll long long
      6 using namespace std;
      7 int n,m,q;
      8 struct node
      9 {
     10     int u,v,nxt;
     11     ll w;
     12 }e[N*2],d[N*2];
     13 int first[N],cnt;
     14 void ade(int u,int v,ll w)
     15 {
     16     e[++cnt].nxt=first[u]; first[u]=cnt;
     17     e[cnt].u=u; e[cnt].v=v; e[cnt].w=w;
     18 }
     19 
     20 int fir[N],cnnt;
     21 void adde(int u,int v,ll w)
     22 {
     23     d[++cnnt].nxt=fir[u]; fir[u]=cnnt;
     24     d[cnnt].u=u; d[cnnt].v=v; d[cnnt].w=w;
     25 }
     26 /*-------kruskal---------*/
     27 int fa[N];
     28 int la(int x)
     29 {
     30     if(fa[x]!=x) fa[x]=la(fa[x]);
     31     return fa[x];
     32 }
     33 bool cmp(node a,node b)
     34 {
     35     return a.w>b.w;
     36 }
     37 void kruskal()
     38 {
     39     for(int i=1;i<=n;i++) fa[i]=i;
     40     sort(e+1,e+cnt+1,cmp);
     41     for(int i=1;i<=cnt;i++)
     42     {
     43         int x=la(e[i].u),y=la(e[i].v);
     44         if(x!=y)
     45         {
     46             fa[x]=y;
     47             adde(e[i].u,e[i].v,e[i].w); 
     48             adde(e[i].v,e[i].u,e[i].w);
     49         }
     50     }
     51 //    cout<<"!!!!";
     52 //    for(int i=1;i<=cnnt;i+=2)
     53 //        printf("%d %d %d
    ",d[i].u,d[i].v,d[i].w);
     54 //    cout<<"!!!!";
     55 }
     56 
     57 /*-----lca------*/
     58 int dep[N],p[N][maxn+5];
     59 ll val[N][maxn+5];
     60 bool vis[N];
     61 void pre()
     62 {
     63     for(int j=1;j<=maxn;j++)
     64         for(int i=1;i<=n;i++)
     65         {
     66             p[i][j]=p[p[i][j-1]][j-1];
     67             val[i][j]=min(val[i][j-1],val[p[i][j-1]][j-1]);
     68         }
     69 }
     70 void dfs(int u,int fath)
     71 {
     72     vis[u]=1;
     73     dep[u]=dep[fath]+1;
     74     p[u][0]=fath;
     75     for(int i=fir[u];i;i=d[i].nxt)
     76     {
     77         int v=d[i].v;
     78         if(vis[v]) continue;
     79         val[v][0]=d[i].w;
     80         dfs(v,u);
     81     }
     82 }
     83 ll lca(int x,int y)
     84 {
     85     ll minx=INF;
     86     if(dep[x]<dep[y]) swap(x,y);
     87     for(int i=maxn;i>=0;i--)
     88         if(dep[x]-(1<<i)>=dep[y])
     89         {
     90             minx=min(minx,val[x][i]);
     91             x=p[x][i];
     92         }
     93     if(x==y) return minx;
     94     for(int i=maxn;i>=0;i--)
     95         if(p[x][i]!=p[y][i])
     96         {
     97             minx=min( minx, min(val[x][i],val[y][i]) );
     98             x=p[x][i],y=p[y][i];
     99         }
    100     minx=min( minx, min(val[x][0],val[y][0]) );
    101     return minx;    
    102 }
    103 /*---------*/
    104 int main()
    105 {
    106     scanf("%d%d",&n,&m);
    107     memset(val,INF,sizeof(val));
    108     for(int i=1,x,y;i<=m;i++)
    109     {
    110         ll z;
    111         scanf("%d%d%lld",&x,&y,&z);
    112         ade(x,y,z);
    113     }
    114     kruskal();
    115     for(int i=1;i<=n;i++)
    116         if(!vis[i]) dfs(i,0);
    117     pre();
    118     scanf("%d",&q);
    119     while(q--)
    120     {
    121         int x,y;
    122         scanf("%d%d",&x,&y);
    123         if(la(x)!=la(y)) printf("-1
    ");
    124         else printf("%lld
    ",lca(x,y));
    125     }
    126     return 0;
    127 }
    128 /*
    129 10 24
    130 4 7 19038
    131 7 10 7375
    132 7 9 17853
    133 9 8 6341
    134 7 2 16976
    135 10 3 2835
    136 10 4 19285
    137 9 4 29193
    138 3 4 4852
    139 3 8 16597
    140 9 1 4138
    141 9 7 21611
    142 7 4 10586
    143 10 4 7821
    144 10 9 25636
    145 3 9 28425
    146 2 3 17229
    147 4 8 11331
    148 9 2 25053
    149 6 4 929
    150 8 3 1738
    151 10 9 28542
    152 1 2 28343
    153 3 5 13215
    154 9
    155 7 5
    156 2 4
    157 10 2
    158 5 10
    159 7 10
    160 4 3
    161 10 1
    162 10 4
    163 8 4
    164 
    165 */
    166 /*
    167 13215
    168 25053
    169 25053
    170 13215
    171 21611
    172 28425
    173 25053
    174 28542
    175 16597
    176 */
  • 相关阅读:
    SQL中的聚合函数
    vs移动团队项目集合
    网页变量的赋值示例
    PRD、MRD、BRD的含义
    w3cschool中jQuery测试结果总结
    sql队伍的胜负情况
    winform中获取当前周次
    select2 的使用
    layui layer table 常见问题
    spring websocket tomcat was websphere9.0 Multiple Endpoints may not be deployed to the same path
  • 原文地址:https://www.cnblogs.com/kylara/p/9748937.html
Copyright © 2011-2022 走看看