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
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
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
正解:倍增+最小生成树
解题报告:
今天考了,那就再发一遍吧。
又重新写了一遍,刚开始觉得是码农,结果20分钟不到就打完了...
显然最小生成树可以满足性质:任意两点之间最大边权最小,然后得到一棵最小生成树树之后就可以在上面跑倍增了。
1 //It is made by jump~ 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 #include <ctime> 9 #include <vector> 10 #include <queue> 11 #include <map> 12 #include <set> 13 using namespace std; 14 typedef long long LL; 15 const int MAXN = 15011; 16 const int MAXM = 60011; 17 int n,m,ans,ecnt,father[MAXN]; 18 int first[MAXN],to[MAXM],next[MAXM],w[MAXM]; 19 int deep[MAXN]; 20 int f[MAXN][15],g[MAXN][15]; 21 struct edge{ 22 int x,y,z; 23 }e[MAXM]; 24 25 inline int getint() 26 { 27 int w=0,q=0; char c=getchar(); 28 while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 29 while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w; 30 } 31 inline bool cmp(edge q,edge qq){ return q.z<qq.z; } 32 inline int find(int x){ if(father[x]!=x) father[x]=find(father[x]); return father[x]; } 33 inline void dfs(int x,int fa){ 34 for(int i=first[x];i;i=next[i]) { 35 int v=to[i]; if(v==fa) continue; 36 f[v][0]=x; g[v][0]=w[i]; deep[v]=deep[x]+1; dfs(v,x); 37 } 38 } 39 40 inline void lca(int x,int y){ 41 if(deep[x]<deep[y]) swap(x,y); 42 int t=0; while((1<<t)<=deep[x]) t++; t--; 43 for(int i=t;i>=0;i--) if(deep[x]-(1<<i)>=deep[y]) ans=max(ans,g[x][i]),x=f[x][i]; 44 if(x==y) return ; 45 for(int i=t;i>=0;i--) { 46 if(f[x][i]!=f[y][i]) { 47 ans=max(g[x][i],ans); ans=max(ans,g[y][i]); 48 x=f[x][i]; y=f[y][i]; 49 } 50 } 51 ans=max(ans,g[x][0]); ans=max(ans,g[y][0]); 52 return ; 53 } 54 55 inline void work(){ 56 n=getint(); m=getint(); int p=getint(); 57 for(int i=1;i<=m;i++) e[i].x=getint(),e[i].y=getint(),e[i].z=getint(); 58 sort(e+1,e+m+1,cmp); for(int i=1;i<=n;i++) father[i]=i; 59 int r1,r2; int x,y; 60 for(int i=1;i<=m;i++) { 61 r1=find(e[i].x); r2=find(e[i].y); 62 if(r1!=r2) { 63 father[r1]=r2; x=e[i].x; y=e[i].y; 64 next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; w[ecnt]=e[i].z; 65 next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x; w[ecnt]=e[i].z; 66 } 67 } 68 for(int i=1;i<=n;i++) if(father[i]==i) { deep[i]=1; dfs(i,0); } 69 for(int j=1;j<=14;j++) for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1],g[i][j]=max(g[i][j-1],g[f[i][j-1]][j-1]); 70 while(p--) { 71 x=getint(); y=getint(); 72 ans=0; lca(x,y); 73 printf("%d\n",ans); 74 } 75 } 76 77 int main() 78 { 79 work(); 80 return 0; 81 }
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!