BZOJ3732: Network

来源:互联网 发布:马东的软件 编辑:程序博客网 时间:2024/06/13 13:30

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

题目传送门

想一看题面,求最大值最小,那不是要跑最小生成树嘛。。。
然后再看,没错,是要跑最小生成树,但是还得加上另外一个东西优化
那就选LCA了!

这肯定满足这是一棵最小生成树对吧,那么我们把这一棵树构造出来
然后再跑LCA的DFS时候顺便更新两个点之间的最大距离即可啊
最后一个问题是要先更新最大值再往上跳
1A水掉~~~~
还有那些100ms的神犇们是怎么做的啊?希望能够有位大神能够分享一下(因为SB作者不会了)
本蒟蒻感激不尽!

代码如下:

#include<cmath>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>using namespace std;struct node{    int x,y,d,next;}a[610000];int len,last[610000];void ins(int x,int y,int d){    len++;    a[len].x=x;a[len].y=y;a[len].d=d;    a[len].next=last[x];last[x]=len;}int bin[25],maxx[210000][25];int dep[210000],f[210000][25];void dfs(int x){    for(int k=last[x];k;k=a[k].next)    {        int y=a[k].y;        if(y!=f[x][0])        {            dep[y]=dep[x]+1;            f[y][0]=x;maxx[y][0]=a[k].d;            dfs(y);        }    }}int lca(int x,int y){    int ans=0;    if(dep[x]>dep[y])        swap(x,y);    for(int i=20;i>=0;i--)        if(dep[y]-dep[x]>=bin[i])            ans=max(ans,maxx[y][i]),y=f[y][i];    if(x==y)return ans;    for(int i=20;i>=0;i--)        if(dep[x]>=bin[i]&&f[x][i]!=f[y][i])            ans=max(ans,max(maxx[x][i],maxx[y][i])),x=f[x][i],y=f[y][i];    return max(ans,max(maxx[x][0],maxx[y][0]));}int fa[210000];int findfa(int x){    if(fa[x]!=x)fa[x]=findfa(fa[x]);    return fa[x];}int n,m,K;struct dd{    int x,y,d;}t[210000];int tlen;bool cmp(node n1,node n2){return n1.d<n2.d;}int main(){    bin[0]=1;    for(int i=1;i<=20;i++)bin[i]=bin[i-1]<<1;    scanf("%d%d%d",&n,&m,&K);    len=0;memset(last,0,sizeof(last));    for(int i=1;i<=n;i++)fa[i]=i;    for(int i=1;i<=m;i++)    {        int x,y,d;        scanf("%d%d%d",&x,&y,&d);        ins(x,y,d);    }    tlen=0;    sort(a+1,a+1+m,cmp);    for(int i=1;i<=m;i++)    {        int x=a[i].x,y=a[i].y;        int tx=findfa(x),ty=findfa(y);        if(tx!=ty)        {            tlen++;            t[tlen].x=x;t[tlen].y=y;t[tlen].d=a[i].d;            fa[tx]=ty;            if(tlen==n-1)break;        }    }    len=0;memset(last,0,sizeof(last));    for(int i=1;i<=tlen;i++)ins(t[i].x,t[i].y,t[i].d),ins(t[i].y,t[i].x,t[i].d);    dfs(1);    for(int j=1;j<=20;j++)        for(int i=1;i<=n;i++)            if(dep[i]>=bin[j])            {                f[i][j]=f[f[i][j-1]][j-1];                maxx[i][j]=max(maxx[i][j-1],maxx[f[i][j-1]][j-1]);            }    while(K--)    {        int x,y;        scanf("%d%d",&x,&y);        printf("%d\n",lca(x,y));    }    return 0;}

by_lmy