BZOJ3732: Network

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


题解Here!

 

在$BZOJ$闲逛的时候发现了这题。
这$TM$不是$NOIP2013\text{货车运输}$嘛。。。
顺手码了。。。
然而这种沙茶题我竟然没有$1A$,真是太失败了。。。
然后发现,我$TM$竟然手抽了,把$will$打成了$f$。。。
手残。。。
所以一发$Kruskal+LCA+\text{树链剖分}$就好了。
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define LSON rt<<1
#define RSON rt<<1|1
#define DATA(x) b[x].data
#define LSIDE(x) b[x].l
#define RSIDE(x) b[x].r
#define MAXN 20010
using namespace std;
int n,m,q,c=1,d=1;
int father[MAXN],head[MAXN],deep[MAXN],son[MAXN],size[MAXN],fa[MAXN],id[MAXN],top[MAXN];
struct Tree{
	int next,to;
}a[MAXN<<1];
struct Segment_Tree{
	int data,l,r;
}b[MAXN<<2];
struct Edge{
	int u,v,w;
	bool used;
}g[MAXN<<1];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
inline bool cmp(const Edge &p,const Edge &q){return p.w<q.w;}
int find(int x){return father[x]==x?x:father[x]=find(father[x]);}
inline void uniun(int x,int y){x=find(x);y=find(y);if(x!=y)father[y]=x;}
inline void add(int x,int y){
	a[c].to=y;a[c].next=head[x];head[x]=c++;
	a[c].to=x;a[c].next=head[y];head[y]=c++;
}
void dfs1(int rt){
	son[rt]=0;size[rt]=1;
	for(int i=head[rt];i;i=a[i].next){
		int will=a[i].to;
		if(!deep[will]){
			deep[will]=deep[rt]+1;
			fa[will]=rt;
			dfs1(will);
			size[rt]+=size[will];
			if(size[son[rt]]<size[will])son[rt]=will;
		}
	}
}
void dfs2(int rt,int f){
	id[rt]=d++;top[rt]=f;
	if(son[rt])dfs2(son[rt],f);
	for(int i=head[rt];i;i=a[i].next){
		int will=a[i].to;
		if(will!=fa[rt]&&will!=son[rt])dfs2(will,will);
	}
}
inline void pushup(int rt){
	DATA(rt)=max(DATA(LSON),DATA(RSON));
}
void buildtree(int l,int r,int rt){
	LSIDE(rt)=l;RSIDE(rt)=r;
	if(l==r){
		DATA(rt)=0;
		return;
	}
	int mid=l+r>>1;
	buildtree(l,mid,LSON);
	buildtree(mid+1,r,RSON);
	pushup(rt);
}
void update(int l,int r,int c,int rt){
	if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
		DATA(rt)=c;
		return;
	}
	int mid=LSIDE(rt)+RSIDE(rt)>>1;
	if(l<=mid)update(l,r,c,LSON);
	if(mid<r)update(l,r,c,RSON);
	pushup(rt);
}
int query(int l,int r,int rt){
	int ans=0;
	if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return DATA(rt);
	int mid=LSIDE(rt)+RSIDE(rt)>>1;
	if(l<=mid)ans=max(ans,query(l,r,LSON));
	if(mid<r)ans=max(ans,query(l,r,RSON));
	return ans;
}
void kruskal(){
	int s=0;
	for(int i=1;i<=m&&s<n-1;i++)
	if(find(g[i].u)!=find(g[i].v)){
		uniun(g[i].u,g[i].v);
		add(g[i].u,g[i].v);
		g[i].used=true;
		s++;
	}
	for(int i=1;i<=n;i++)
	if(!deep[i]){
		deep[i]=1;
		dfs1(i);
		dfs2(i,i);
	}
	buildtree(1,n,1);
	for(int i=1;i<=m;i++)
	if(g[i].used){
		if(deep[g[i].u]>deep[g[i].v])swap(g[i].u,g[i].v);
		update(id[g[i].v],id[g[i].v],g[i].w,1);
	}
}
void solve(int x,int y){
	int s=0;
	while(top[x]!=top[y]){
		if(deep[top[x]]<deep[top[y]])swap(x,y);
		s=max(s,query(id[top[x]],id[x],1));
		x=fa[top[x]];
	}
	if(deep[x]>deep[y])swap(x,y);
	if(x!=y)s=max(s,query(id[x]+1,id[y],1));
	printf("%d\n",s);
}
void work(){
	int x,y;
	while(q--){
		x=read();y=read();
		solve(x,y);
	}
}
void init(){
	n=read();m=read();q=read();
	for(int i=1;i<=m;i++){
		g[i].u=read();g[i].v=read();g[i].w=read();
		g[i].used=false;
	}
	for(int i=1;i<=n;i++)father[i]=i;
	sort(g+1,g+m+1,cmp);
	kruskal();
}
int main(){
	init();
	work();
    return 0;
}

 

posted @ 2018-08-21 00:08  符拉迪沃斯托克  阅读(108)  评论(0编辑  收藏  举报
Live2D