【UVA 11354】 Bond (最小瓶颈生成树、树上倍增)
【题意】
n个点m条边的图 q次询问 找到一条从s到t的一条边 使所有边的最大危险系数最小
Input
There will be at most 5 cases in the input file.
The first line of each case contains two integers N, M (2 ≤ N ≤ 50000, 1 ≤ M ≤ 100000) – number
of cities and roads. The next M lines describe the roads. The i-th of these lines contains three integers:
xi, yi, di (1 ≤ xi, yi ≤ N, 0 ≤ di ≤ 10^9) – the numbers of the cities connected by the i-th road and its
dangerousness.
Description of the roads is followed by a line containing an integer Q (1 ≤ Q ≤ 50000), followed by
Q lines, the i-th of which contains two integers si and ti (1 ≤ si
, ti ≤ N, si ̸= ti).
Consecutive input sets are separated by a blank line.
Output
For each case, output Q lines, the i-th of which contains the minimum dangerousness of a path between
cities si and ti
. Consecutive output blocks are separated by a blank line.
The input file will be such that there will always be at least one valid path.
Sample Input
4 5
1 2 10
1 3 20
1 4 100
2 4 30
3 4 10
2
1 4
4 1
2 1
1 2 100
1
1 2
Sample Output
20
20
100
【分析】
很明显是最小瓶颈生成树。
有一个定理:最小生成树是最小瓶颈生成树,但是最小瓶颈生成树不一定是最小生成树。
我们只要求最小生成树就好了。
不过这题n较大,不能n^2预处理,所以我们先把树求出来,然后询问的时候 树剖或者倍增 都可以。
应该是,倍增耗空间但是时间少一个log , 树剖省一点空间但是 时间多一个log (要多一个数据结构维护)
我上次就打一题倍增MLE了TAT,不过这题正解是倍增,不知道树剖+线段树能不能过。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 using namespace std; 8 #define Maxn 50010 9 #define Maxm 1000010 10 #define INF 0xfffffff 11 12 struct node 13 { 14 int x,y,c,next; 15 }t[Maxn*2],tt[Maxm]; 16 int len; 17 int first[Maxn]; 18 19 bool cmp(node x,node y) {return x.c<y.c;} 20 int mymax(int x,int y) {return x>y?x:y;} 21 22 int fa[Maxn]; 23 int ffind(int x) 24 { 25 if(fa[x]!=x) fa[x]=ffind(fa[x]); 26 return fa[x]; 27 } 28 29 void ins(int x,int y,int c) 30 { 31 t[++len].x=x;t[len].y=y;t[len].c=c; 32 t[len].next=first[x];first[x]=len; 33 } 34 35 int f[Maxn][20],g[Maxn][20],dep[Maxn]; 36 37 void dfs(int x,int ff,int l) 38 { 39 dep[x]=dep[ff]+1; 40 g[x][0]=ff; 41 for(int i=1;(1<<i)<=dep[x];i++) 42 g[x][i]=g[g[x][i-1]][i-1]; 43 f[x][0]=l; 44 for(int i=1;(1<<i)<=dep[x];i++) 45 f[x][i]=mymax(f[x][i-1],f[g[x][i-1]][i-1]); 46 for(int i=first[x];i;i=t[i].next) if(t[i].y!=ff) 47 dfs(t[i].y,x,t[i].c); 48 } 49 50 int ffind(int x,int y) 51 { 52 int ans=0; 53 while(dep[x]!=dep[y]) 54 { 55 int z; 56 if(dep[x]<dep[y]) z=x,x=y,y=z; 57 for(int i=18;i>=0;i--) if(dep[x]-(1<<i)>=dep[y]) 58 ans=mymax(ans,f[x][i]),x=g[x][i]; 59 } 60 if(x==y) return ans; 61 if(x!=y) 62 { 63 for(int i=18;i>=0;i--) if(g[x][i]!=g[y][i]&&dep[x]>=(1<<i)) 64 ans=mymax(ans,f[x][i]),ans=mymax(ans,f[y][i]), 65 x=g[x][i],y=g[y][i]; 66 } 67 ans=mymax(ans,f[x][0]);ans=mymax(ans,f[y][0]); 68 return ans; 69 } 70 71 int main() 72 { 73 int n,m; 74 bool ok=0; 75 while(scanf("%d%d",&n,&m)!=EOF) 76 { 77 if(ok) printf("\n"); 78 ok=1; 79 for(int i=1;i<=m;i++) 80 { 81 scanf("%d%d%d",&tt[i].x,&tt[i].y,&tt[i].c); 82 } 83 sort(tt+1,tt+1+m,cmp); 84 int cnt=0; 85 for(int i=1;i<=n;i++) fa[i]=i; 86 len=0; 87 memset(first,0,sizeof(first)); 88 for(int i=1;i<=m;i++) 89 { 90 if(ffind(tt[i].x)!=ffind(tt[i].y)) 91 { 92 fa[ffind(tt[i].x)]=ffind(tt[i].y); 93 cnt++; 94 ins(tt[i].x,tt[i].y,tt[i].c); 95 ins(tt[i].y,tt[i].x,tt[i].c); 96 } 97 if(cnt==n-1) break; 98 } 99 dep[0]=0; 100 dfs(1,0,0); 101 int q; 102 scanf("%d",&q); 103 for(int i=1;i<=q;i++) 104 { 105 int x,y; 106 scanf("%d%d",&x,&y); 107 printf("%d\n",ffind(x,y)); 108 } 109 } 110 return 0; 111 }
2016-11-01 08:16:45