gym 101081F Auction of Services 最小生成树扩展、lca树上倍增

gym 101081F

题意:给出一个无向图,定义一条路径的价值为 这条路径上最大的边权值。 有 Q 个询问,每次询问两个点间所有路径价值的最小值。

tags: 最小生成树的应用。

最小瓶颈路 :给定一个加权无向图,并给定无向图中两个结点u和v,求u到v的一条路径,使得路径上边的最大权值最小。   

所有两个点间的最小路径价值就是在最小生成树上。 构出最小生成树后,求树上两点之间的最大边,这个倍增或树链剖分都可以解决。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 200005;

int tot, head[N];
struct Edge {
    int from, to, w, next;
    bool friend operator < (Edge a, Edge b) {
        return a.w < b.w;
    }
} e1[N], e2[N];
void Add(int u, int v, int w)
{
    e2[tot]=(Edge){u,v,w,head[u] };  head[u]=tot++;
}

int n, m, q, fa[N];
int Find(int x) { return fa[x]==x ? x : fa[x]=Find(fa[x]); }
bool Unite(int a, int b)
{
    int faa=Find(a), fab=Find(b);
    if(faa==fab) return false;
    else { fa[fab]=faa;  return true;  }
}

int dep[N], p[N][30], mx[N][30];
void dfslca(int u, int fa, int w)
{
    dep[u]=dep[fa]+1,  p[u][0]=fa,  mx[u][0]=w;
    for(int i=head[u]; i!=-1; i=e2[i].next)
        if(e2[i].to!=fa)  dfslca(e2[i].to, u, e2[i].w);
}
void Initlca()
{
    mes(mx, 0);  mes(p, -1);  mes(dep, 0);  dep[0]=-1;
    dfslca(1, 0, 0);
    for(int j=1; (1<<j)<=n; ++j)
        for(int i=1; i<=n; ++i) if(p[i][j-1]!=-1)
            mx[i][j]=max(mx[i][j-1], mx[p[i][j-1]][j-1]),  p[i][j]=p[p[i][j-1]][j-1];
}
int solve(int a, int b)
{
    int i, j, ans=0;
    if(dep[a] < dep[b]) swap(a, b);
    for(i=0; (1<<i)<=dep[a]; ++i) ;   --i;
    for(j=i; j>=0; --j)
        if(dep[a]-(1<<j) >= dep[b])
            ans=max(ans, mx[a][j]), a=p[a][j];
    if(a==b) return ans;
    for(j=i; j>=0; --j)
        if(p[a][j]!=-1 && p[a][j]!=p[b][j])
        {
            ans = max(ans, max(mx[a][j], mx[b][j]));
            a=p[a][j], b=p[b][j];
        }
    return ans=max(ans, max(mx[a][0], mx[b][0]));
}

int main()
{
    scanf("%d%d", &n, &m);
    mes(head, -1);  tot=0;
    rep(i,1,n) fa[i] = i;
    int u, v, w;
    rep(i,1,m)
    {
        scanf("%d%d%d", &u, &v, &w);
        e1[i] = (Edge) {u,v,w,0 };
    }
    sort(e1+1, e1+1+m);
    rep(i,1,m) if(Unite(e1[i].from, e1[i].to))
        Add(e1[i].from, e1[i].to, e1[i].w),  Add(e1[i].to, e1[i].from, e1[i].w);
    Initlca();
    scanf("%d", &q);
    rep(i,1,q)
    {
        scanf("%d%d", &u, &v);
        printf("%d
", solve(u, v));
    }

    return 0;
}
原文地址:https://www.cnblogs.com/sbfhy/p/7520096.html