【刷题】BZOJ 3732 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 < = 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

Solution

kruskal重构树裸题
建出重构树之后找到两个点的 \(LCA\) ,其权值就是答案

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=15000+10,MAXM=30000+10;
int n,m,k,e,beg[MAXN<<1],to[MAXN<<2],nex[MAXN<<2],val[MAXN<<1],Jie[20][MAXN<<1],fa[MAXN<<1],cnt,dep[MAXN<<1];
struct node{
	int u,v,w;
	inline bool operator < (const node &A) const {
		return w<A.w;
	};
};
node side[MAXM];
template<typename T> inline void read(T &x)
{
	T data=0,w=1;
	char ch=0;
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
	x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
	if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline int found(int x)
{
	if(x!=fa[x])fa[x]=found(fa[x]);
	return fa[x];
}
inline void insert(int x,int y)
{
	to[++e]=y;
	nex[e]=beg[x];
	beg[x]=e;
}
inline void dfs(int x,int f)
{
	dep[x]=dep[f]+1;
	for(register int i=beg[x];i;i=nex[i])
		if(to[i]!=f)dfs(to[i],x);
}
inline int LCA(int u,int v)
{
	if(dep[u]<dep[v])std::swap(u,v);
	if(dep[u]>dep[v])
		for(register int i=19;i>=0;--i)
			if(dep[Jie[i][u]]>=dep[v])u=Jie[i][u];
	if(u==v)return u;
	for(register int i=19;i>=0;--i)
		if(Jie[i][u]!=Jie[i][v])u=Jie[i][u],v=Jie[i][v];
	return Jie[0][u];
}
int main()
{
	read(n);read(m);read(k);
	for(register int i=1;i<=m;++i)
	{
		int u,v,w;read(u);read(v);read(w);
		side[i]=(node){u,v,w};
	}
	std::sort(side+1,side+m+1);
	cnt=n;
	for(register int i=1;i<=n+n-1;++i)fa[i]=i;
	for(register int i=1,u,v;i<=m;++i)
	{
		u=found(side[i].u),v=found(side[i].v);
		if(u==v)continue;
		else
		{
			++cnt;val[cnt]=side[i].w;
			insert(u,cnt);insert(cnt,u);
			insert(v,cnt);insert(cnt,v);
			fa[u]=fa[v]=Jie[0][u]=Jie[0][v]=cnt;
		}
	}
	dfs(cnt,0);
	for(register int j=1;j<=19;++j)
		for(register int i=1;i<=cnt;++i)Jie[j][i]=Jie[j-1][Jie[j-1][i]];
	while(k--)
	{
		int u,v;read(u);read(v);
		write(val[LCA(u,v)],'\n');
	}
	return 0;
}
posted @ 2018-08-04 10:52  HYJ_cnyali  阅读(165)  评论(0编辑  收藏  举报