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

题解:

这题首先要在最小中求最大。
我们注意到最小生成树用的就是将每一条边都缩到最小的贪心想法,所以我们可以直接刷一次kruskal建成一颗树,接下来就只要刷lca,在这过程中同时记录最大边是那条就行了。。。

代码如下:

#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=15005,maxm=30005;
int n,m,Q,tot,fa[maxn],lnk[maxn],nxt[2*maxm],son[2*maxm],dep[maxn],w[2*maxm],f[maxn][20],sum[maxn][20];
bool vis[maxn];
struct dyt{
    int x,y,z;
    bool operator <(const dyt &b) const{return z<b.z;}
}a[maxm];
inline int read(){
    int x=0; char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
    return x;
}
void add(int x,int y,int z){son[++tot]=y,nxt[tot]=lnk[x],w[tot]=z,lnk[x]=tot;}
int getfa(int x){if (fa[x]!=x) fa[x]=getfa(fa[x]); return fa[x];}
void dfs(int x){
    for (int j=lnk[x];j;j=nxt[j])
    if (!vis[son[j]]) {vis[son[j]]=1,dep[son[j]]=dep[x]+1,f[son[j]][0]=x,sum[son[j]][0]=w[j]; dfs(son[j]);}
}
void kruskal(){
    sort(a+1,a+1+m);
    for (int i=1;i<=n;i++) fa[i]=i;
    for (int i=1;i<=m;i++) {
        int fax=getfa(a[i].x),fay=getfa(a[i].y);
        if (fax!=fay) {
            fa[fax]=fay; add(a[i].x,a[i].y,a[i].z); add(a[i].y,a[i].x,a[i].z);
        }
    }
    vis[1]=dep[1]=1; dfs(1);
}
void build(){
    for (int j=1;j<=19;j++)
    for (int i=1;i<=n;i++)
    f[i][j]=f[f[i][j-1]][j-1],sum[i][j]=max(sum[i][j-1],sum[f[i][j-1]][j-1]);
}
int get(int x,int y){
    if (dep[x]<dep[y]) swap(x,y); int ret=0;
    for (int i=19;i>=0;i--) if (dep[f[x][i]]>=dep[y]) ret=max(ret,sum[x][i]),x=f[x][i];
    if (x==y) return ret;
    for (int i=19;i>=0;i--) if (f[x][i]!=f[y][i]) ret=max(max(ret,sum[x][i]),sum[y][i]),x=f[x][i],y=f[y][i];
    return max(max(ret,sum[x][0]),sum[y][0]);
}
int main(){
    n=read(),m=read(),Q=read();
    for (int i=1;i<=m;i++) a[i].x=read(),a[i].y=read(),a[i].z=read();
    kruskal(); build();
    while (Q--){int x=read(),y=read(); printf("%d\n",get(x,y));}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dyt_b/article/details/79887368
今日推荐