倍增加强学习笔记

加强?不可能的!

因为这几次考试中的倍增孤都挂了,而且发现自己倍增打得比较少,所以用一篇随笔来再学习。

直接开题:

洛谷 P1967【货车运输】

题意:给定一张图,每条边上有限重,有Q个询问,每个询问求x到y的最大运输重量。

开局思路暴力?一看范围……

算了吧,要是孤还想活着就别这么打……

我们再看一下,也就是说x到y中间有很多道路,我们要求出这些道路最小值的最大值。

不妨先考虑如何保证最大,我们可以从中选出一些边,保证联通的情况下有最小值的最大值

诶,好像就是要构一棵最大生成树,再跑LCA就可以啦(毕竟暴跳就会TLE啊)

上代码:

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int f=1,w=0;char x=0;
    while(x<'0'||x>'9') {if(x=='-') f=-1; x=getchar();}
    while(x!=EOF&&x>='0'&&x<='9') {w=(w<<3)+(w<<1)+(x^48);x=getchar();}
    return w*f;
}
int n,m,num_edge,fa[200001][21],w[200001][21],q;
struct Edge{int u,v,w;} line[200001];
int head[50001],f[200001],vis[200001],dep[200001];
struct Tree{int next,to,dis;} edge[200001];
inline bool cmp(Edge a,Edge b) {return a.w>b.w;}
inline int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
inline void add(int from,int to,int dis)
{
    edge[++num_edge].next=head[from];
    edge[num_edge].to=to;
    edge[num_edge].dis=dis;
    head[from]=num_edge;
}
void dfs(int pos)
{
    vis[pos]=1;
    for(int i=head[pos];i;i=edge[i].next)
        if(!vis[edge[i].to])
        {
            dep[edge[i].to]=dep[pos]+1;
            fa[edge[i].to][0]=pos;
            w[edge[i].to][0]=edge[i].dis;
            dfs(edge[i].to);
        }
}
inline int LCA(int x,int y)
{
    if(find(x)!=find(y)) return -1;
    if(dep[x]>dep[y]) swap(x,y);
    int ans=999999999;
    for(int i=20;i>=0;i--)
        if(dep[fa[y][i]]>=dep[x])
        {
            ans=min(ans,w[y][i]);
            y=fa[y][i];
        }
    if(x==y) return ans;
    for(int i=20;i>=0;i--)
        if(fa[x][i]!=fa[y][i])
        {
            ans=min(ans,min(w[x][i],w[y][i]));
            y=fa[y][i];
            x=fa[x][i];
        }
    ans=min(ans,min(w[x][0],w[y][0]));
    return ans;
}
int main(){
    n=read();
    m=read();
    for(int i=1;i<=m;i++)
        line[i].u=read(),line[i].v=read(),line[i].w=read();
    sort(line+1,line+m+1,cmp);
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=1;i<=m;i++)
    {
        int u=find(line[i].u);
        int v=find(line[i].v);
        if(u!=v) f[u]=v,add(line[i].u,line[i].v,line[i].w),add(line[i].v,line[i].u,line[i].w);
    }
    for(int i=1;i<=n;i++)
        if(!vis[i])
        {
            dep[i]=1;
            dfs(i);
            fa[i][0]=i;
            w[i][0]=999999999;
        }
    for(int j=1;j<=20;j++)
        for(int i=1;i<=n;i++)
            {
                fa[i][j]=fa[fa[i][j-1]][j-1];
                w[i][j]=min(w[i][j-1],w[fa[i][j-1]][j-1]);
            }
    q=read();
    for(int i=1;i<=q;i++)
    {
        int x=read(),y=read();
        printf("%d
",LCA(x,y));
    }
}
原文地址:https://www.cnblogs.com/wo-shi-zhen-de-cai/p/10387859.html