bzoj 3732: Network

3732: Network

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1880  Solved: 894

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

 思路:因为要最大边最小所以很明显是跑最小瓶颈生成树。

跑完后倍增求最大值。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 30000
#define LL long long
using namespace std;
LL maxn[MAXN];
int n,m,k,tot,num,numb;
int fa[MAXN*10],dad[MAXN*10],deep[MAXN*10];
int to[MAXN*10],head[MAXN*10],net[MAXN*10],cap[MAXN*10];
struct nond{
    int x,y,z;
}edge[MAXN];
void add(int u,int v,int w){
    edge[++tot].x=u;edge[tot].y=v;edge[tot].z=w;
}
void insert(int u,int v,int w){
    to[++num]=v;net[num]=head[u];cap[num]=w;head[u]=num;
    to[++num]=u;net[num]=head[v];cap[num]=w;head[v]=num;
}
int cmp(nond a,nond b){
    return a.z<b.z;
}
int find(int x){
    if(fa[x]==x)    return fa[x];
    else return fa[x]=find(fa[x]);
}
void dfs(int x){
    deep[x]=deep[dad[x]]+1;
    for(int i=head[x];i;i=net[i])
        if(dad[x]!=to[i]){
            dad[to[i]]=x;
            maxn[to[i]]=cap[i];
            dfs(to[i]);
        }
}
LL lca(int x,int y){
    LL ans=-1;
    if(deep[x]>deep[y])    swap(x,y);
    while(deep[y]>deep[x]){
        ans=max(ans,maxn[y]);
        y=dad[y];
    }
    while(x!=y){
        ans=max(ans,max(maxn[x],maxn[y]));
        x=dad[x];
        y=dad[y];
    }
    return ans;
}
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
    }
    sort(edge+1,edge+1+tot,cmp);
    for(int i=1;i<=n;i++)    fa[i]=i;
    for(int i=1;i<=tot;i++){
        int dx=find(edge[i].x);
        int dy=find(edge[i].y);
        if(dx==dy)    continue;
        numb++;
        fa[dx]=dy;
        insert(edge[i].x,edge[i].y,edge[i].z);
        if(numb==n-1)    break;
    }
    dfs(1);
    for(int i=1;i<=k;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        printf("%d\n",lca(x,y));
    }
}

 

posted @ 2017-08-21 08:32  一蓑烟雨任生平  阅读(281)  评论(0编辑  收藏  举报