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\n",ans);        
139     }
140     return 0;
141 }

 

posted @ 2016-05-07 14:37  ljh_2000  阅读(377)  评论(0编辑  收藏  举报