• 倍增加强学习笔记


    加强?不可能的!

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

    直接开题:

    洛谷 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));
        }
    }
  • 相关阅读:
    C++之路进阶——codevs2439(降雨量)
    C++之路进阶——codevs2933(诗人小G)
    C++之路进阶——bzoj2879(美食节)
    C++之路进阶——bzoj1934(善意的投票)
    C++之路进阶——bzoj3876(支线剧情)
    C++之路进阶——codevs1281(Xn数列)
    八数码难题
    道路游戏
    细胞分裂
    最长链
  • 原文地址:https://www.cnblogs.com/wo-shi-zhen-de-cai/p/10387859.html
Copyright © 2020-2023  润新知