SSL2779 2017年10月21日提高组 Heatwave(lca+rmq)

来源:互联网 发布:查看本机的mac地址 编辑:程序博客网 时间:2024/05/17 23:30

2017年10月21日提高组 Heatwave

Description

给你N个点的无向连通图,图中有M条边,第j条边的长度为: d_j.
  现在有 K个询问。
  每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?

Input

  文件名为heatwave.in
  第一行: 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

  对每个询问,输出最长的边最小值是多少。
  
分析:最长边的最小值显然是最小生成树,然后树上倍增在求lca的过程中统计最长边。

代码

#include <cstdio>#include <algorithm>#define maxn 40000using namespace std;struct arr{    int to,w,nxt;}a[maxn];struct edge{    int x,y,w;}b[maxn];int n,m,k,l,ans;int f[maxn][21],dis[maxn][21];int fa[maxn],v[maxn],ls[maxn],dep[maxn];int so(edge p,edge q){    return p.w<q.w;}int max(int x,int y){    return x>y?x:y;}void add(int p,int q,int z){    a[++l].to=q;    a[l].nxt=ls[p];    a[l].w=z;    ls[p]=l;}int find(int x){    if (fa[x]==x) return x;    return fa[x]=find(fa[x]);}int mst(){    for (int i=1;i<=n;i++)        fa[i]=i;    for (int i=1;i<=m;i++)    {        int u=find(b[i].x);        int v=find(b[i].y);        if (u!=v)        {            fa[u]=v;            add(b[i].x,b[i].y,b[i].w);            add(b[i].y,b[i].x,b[i].w);        }    }}int dfs(int s,int far){    f[s][0]=far;    for (int i=ls[s];i;i=a[i].nxt)        if (v[a[i].to]==0)        {            v[a[i].to]=1;            dep[a[i].to]=dep[s]+1;            dis[a[i].to][0]=a[i].w;            dfs(a[i].to,s);                 }}void lca(int p,int q){    if (dep[p]<dep[q])    {        p^=q;q^=p;p^=q;    }    for (int i=20;i>=0;i--)        if (dep[q]<=dep[f[p][i]])        {            ans=max(ans,dis[p][i]);            p=f[p][i];        }    if (p==q) return;    for (int i=20;i>=0;i--)        if (f[p][i]!=f[q][i])        {            ans=max(max(dis[q][i],dis[p][i]),ans);            p=f[p][i];            q=f[q][i];        }    ans=max(ans,max(dis[p][0],dis[q][0]));    return;}int main(){    scanf("%d%d%d",&n,&m,&k);    for (int i=1;i<=m;i++)        scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].w);    sort(b+1,b+m+1,so);    mst();    dep[1]=1;    v[1]=1;    dfs(1,0);    for (int j=1;j<=20;j++)        for (int i=1;i<=n;i++)        {            f[i][j]=f[f[i][j-1]][j-1];            dis[i][j]=max(dis[i][j-1],dis[f[i][j-1]][j-1]);        }    for (int i=1;i<=k;i++)    {        int x,y;        ans=0;        scanf("%d%d",&x,&y);        lca(x,y);        printf("%d\n",ans);    }}
原创粉丝点击