• BZOJ3732 Network


     

    Description

    给你N个点的无向图 (1 <= N <= 15,000),记为:1…N。 
    图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000).

    现在有 K个询问 (1 < = K < = 15,000)。 
    每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?

    Input

    第一行: N, M, K。 
    第2..M+1行: 三个正整数:X, Y, and D (1 <= X <=N; 1 <= Y <= N). 表示X与Y之间有一条长度为D的边。 
    第M+2..M+K+1行: 每行两个整数A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?

    Output

     对每个询问,输出最长的边最小值是多少。

    Sample Input

    6 6 8
    1 2 5
    2 3 4
    3 4 3
    1 4 8
    2 5 7
    4 6 2
    1 2
    1 3
    1 4
    2 3
    2 4
    5 1
    6 2
    6 1

    Sample Output

    5
    5
    5
    4
    4
    7
    4
    5

    HINT

    1 <= N <= 15,000 

    1 <= M <= 30,000 

    1 <= d_j <= 1,000,000,000 

    1 <= K <= 15,000 

    正解:最小生成树+倍增lca

    解题报告:

      大概题意是给定一个无向图,然后求两点之间的路径中权值最大的边的最小值

      望着这道题10分钟之后感觉做不到一眼秒题,老老实实画图,结果发现我真是太弱了,居然没有发现满足题意的条件竟然是最小生成树的性质。。。

      显然先构出最小生成树,其他的边是没有用的,可以删掉。

      构出最小生成树之后,就考虑两点间的路径上的最大值。

      可以在求lca的时候顺便维护一下就可以了。

      我开始打了一个树链剖分+线段树,然而上午脑袋不是很清白,而且鬼畜的BZOJ,居然迷之RE了两次。

      好吧,被迫改用倍增,然后就过了,并不知道为什么树链剖分哪里打萎了。

      (这道题其实就是NOIP2013的原题货车运输的改版的好吗,几乎一模一样)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<cstdlib>
      6 #include<algorithm>
      7 #include<vector>
      8 #include<queue>
      9 #include<string>
     10 #ifdef WIN32   
     11 #define OT "%I64d"
     12 #else
     13 #define OT "%lld"
     14 #endif
     15 using namespace std;
     16 typedef long long LL;
     17 int n,m;
     18 int u[200011],to[200011],w[200011];
     19 int first[200011],next[200011],u1[200011],to1[200011],ww[200011];
     20 int father[200011],height[200011];
     21 int f[100011][16],quan[100011][16];
     22 
     23 inline int getint(){
     24     int q=0,w=0;
     25     char c=getchar();
     26     while(c!='-' && ( c<'0' || c>'9' ) ) c=getchar();
     27     if(c=='-') q=1,c=getchar();
     28     while(c>='0' && c<='9') w=w*10+c-'0',c=getchar();
     29     return q?-w:w;    
     30 }
     31 
     32 inline void qsort(int l,int r)
     33 {
     34       int i=l,j=r;
     35       int mid=w[(i+j)/2],p;
     36       do
     37       {
     38          while(w[i]<mid)i++;
     39          while(w[j]>mid)j--;
     40          if(i<=j)
     41          {
     42              p=w[i];w[i]=w[j];w[j]=p;  
     43              p=u[i];u[i]=u[j];u[j]=p;  
     44              p=to[i];to[i]=to[j];to[j]=p;    
     45              i++;
     46              j--;   
     47          }    
     48       }while(i<=j);  
     49       if(i<r)qsort(i,r);
     50       if(l<j)qsort(l,j);
     51 }
     52 
     53 inline int find(int x){
     54       if(father[x]!=x) father[x]=find(father[x]);
     55       return father[x];  
     56 }
     57 
     58 inline void hebing(int x,int y){
     59        father[y]=x; 
     60 }
     61 
     62 inline void dfs(int x,int deep){
     63      height[x]=deep;
     64      for(int i=1;i<=15;i++){
     65            f[x][i]=f[ f[x][i-1] ][i-1];
     66            quan[x][i]=max( quan[x][i-1],quan[ f[x][i-1] ][i-1] );
     67      }
     68      for(int i=first[x];i;i=next[i]){
     69           if(height[to1[i]]==0)
     70           {
     71             f[ to1[i] ][0]=x;
     72             quan[ to1[i] ][0]=ww[i];
     73             dfs(to1[i],deep+1);        
     74           }
     75      }      
     76 }
     77 
     78 int lca(int x,int y){
     79        if(height[x]<height[y]) { int t=x;x=y;y=t; }
     80        int t=0;
     81        while((1<<t) <=height[x]) t++;
     82        t--;
     83        int ans1=-0x7ffffff,ans2=-0x7ffffff;
     84        for(int i=t;i>=0;i--){
     85           if(height[x]-(1<<i)>=height[y]) {
     86               ans1=max(ans1,quan[x][i]);
     87               x=f[x][i];        
     88           }
     89        }  
     90        if(x==y) return ans1;
     91        for(int i=t;i>=0;i--){
     92           if(f[x][i]!=f[y][i]){
     93              ans1=max(ans1,quan[x][i]); ans2=max(ans2,quan[y][i]);
     94              x=f[x][i];y=f[y][i];                     
     95           }        
     96        }
     97        int zong1,zong2;
     98        zong1=max(ans1,quan[x][0]);
     99        zong2=max(ans2,quan[y][0]);
    100        return max(zong1,zong2);
    101 }
    102 
    103 inline void work(){
    104     qsort(1,m);
    105     for(int i=1;i<=n;i++)    father[i]=i; 
    106     int i=1,j=0;
    107     int yigong=0;
    108     while(i<=m){
    109        int r1=find(u[i]);int r2=find(to[i]);
    110        hebing(r1,r2);
    111        yigong++;            
    112        j++; next[j]=first[u[i]]; first[u[i]]=j;ww[j]=w[i]; to1[j]=to[i]; u1[j]=u[i];
    113        j++; next[j]=first[to[i]]; first[to[i]]=j;ww[j]=w[i]; to1[j]=u[i]; u1[j]=to[i];
    114        i++;
    115        while(find(u[i])==find(to[i]) && i<=m) 
    116            i++;
    117     }
    118     for(int i=1;i<=n;i++)
    119      if(father[i]==i)
    120      {
    121         dfs(i,1);
    122      }
    123 }
    124 
    125 int main()
    126 {
    127     n=getint();m=getint();int q=getint();
    128     int ljh,jump,jumpjump;
    129     for(int i=1;i<=m;i++){
    130           ljh=getint();jump=getint();jumpjump=getint();
    131           u[i]=ljh;to[i]=jump;w[i]=jumpjump;  
    132     } 
    133     
    134     work();
    135     for(int i=1;i<=q;i++){
    136         ljh=getint();jump=getint();
    137         int ans=lca(ljh,jump);
    138         printf("%d
    ",ans);        
    139     }
    140     return 0;
    141 }
  • 相关阅读:
    Android 图表控件的使用
    使用kotlin开发android
    Servlet 使用介绍(3)
    Servlet 使用介绍(2)
    Servlet 使用介绍(1)
    Android 中的style和Theme的使用
    Java Web工程目录结构
    IP地址解析
    Android 音视频深入 十六 FFmpeg 推流手机摄像头,实现直播 (附源码下载)
    Android 音视频深入 十五 FFmpeg 推流mp4文件(附源码下载)
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5468335.html
Copyright © 2020-2023  润新知