zoukankan      html  css  js  c++  java
  • 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 ext{货车运输}$嘛。。。
    顺手码了。。。
    然而这种沙茶题我竟然没有$1A$,真是太失败了。。。
    然后发现,我$TM$竟然手抽了,把$will$打成了$f$。。。
    手残。。。
    所以一发$Kruskal+LCA+ ext{树链剖分}$就好了。
    附代码:
    #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
    ",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;
    }
    
  • 相关阅读:
    Python3之random模块常用方法
    Go语言学习笔记(九)之数组
    Go语言学习笔记之简单的几个排序
    Go语言学习笔记(八)
    Python3之logging模块
    Go语言学习笔记(六)
    123. Best Time to Buy and Sell Stock III(js)
    122. Best Time to Buy and Sell Stock II(js)
    121. Best Time to Buy and Sell Stock(js)
    120. Triangle(js)
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9508958.html
Copyright © 2011-2022 走看看