BZOJ 3732 Network

3732: Network

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2392  Solved: 1135
[Submit][Status][Discuss]

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 < = 20,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

 

昨天翻Mybing博客的时候发现了     http://www.cnblogs.com/mybing/p/8610357.html#3928587

这道题很裸的做法就是跑一下kruskal,对于每次询问输出x到lca(x,y),以及y到lca(x,y)中间的最大值即可

还有一种就是kruskal重构树,但是貌似拿来做这道题的话有点大材小用了  不过拿来练板子还是可以的

具体什么是kruskal重构树  https://blog.csdn.net/wu_tongtong/article/details/77601523

kruskal有一些很优秀的性质,比如说这棵树是一个大根堆,有二叉性质...

等到以后用到这行性质再说吧

#include <bits/stdc++.h>
#define ll long long
#define inf 1e9+10
using namespace std;
inline int read(){
	int x=0;int f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
const int MAXN=1e5+10;
struct node{
	int y,next;
}e[MAXN];
int linkk[MAXN],len=0,f[MAXN][30],dep[MAXN],n,m,fa[MAXN],v[MAXN],p;
struct edge{
	int x,y,v;
}d[MAXN];
inline void insert(int x,int y){
	e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;
}
inline bool cmp(edge n,edge m){
	return n.v<m.v;
}
inline int getfa(int x){
	return x==fa[x]?x:fa[x]=getfa(fa[x]); 
}
void kruskal(){
	for(int i=1;i<=n;i++) fa[i]=i;
	p=n;
	sort(d+1,d+m+1,cmp);
	for(int i=1;i<=m;i++){
		int x=getfa(d[i].x);int y=getfa(d[i].y);
		if(x!=y){
			p++;fa[x]=p;fa[y]=p;v[p]=d[i].v;fa[p]=p;
			insert(p,x);insert(p,y);
		}
	}
}
inline void getdep(int x,int fa){
	f[x][0]=fa;
	for(int i=linkk[x];i;i=e[i].next){
		dep[e[i].y]=dep[x]+1;getdep(e[i].y,x);
	}
}
void getanser(){
	for(int i=1;i<=24;i++){
		for(int j=1;j<=p;j++){
			f[j][i]=f[f[j][i-1]][i-1];
		}
	}
}
inline int getlca(int x,int y){
	if(x==y) return x;
	if(dep[x]<dep[y]) swap(x,y);
	for(int i=24;i>=0;i--){
		if(dep[x]-(1<<i)>=dep[y]){
			x=f[x][i];
		}
	}
	if(x==y) return x;
	for(int i=24;i>=0;i--){
		if(f[x][i]!=f[y][i]&&f[x][i]){
			x=f[x][i];y=f[y][i];
		}
	}
	return f[x][0];
}
int main(){
	n=read();m=read();int t=read();
	for(int i=1;i<=m;i++){
		d[i].x=read();d[i].y=read();d[i].v=read();
	}
	kruskal();
	dep[p]=1;
	getdep(p,0);getanser();
	for(int i=1;i<=t;i++){
		int x=read();int y=read();
		printf("%d\n",v[getlca(x,y)]);
	}
	return 0;
}

  

posted @ 2018-05-21 21:53  zhangenming  阅读(232)  评论(2编辑  收藏  举报