• luogu P1396 营救


    原题链接:https://www.luogu.org/problem/show?pid=1396

    刚一看到这个题,马上就想起来前几天刚做的货车运输,于是迅速地敲了个最小生成树+lca求路径上最长边,写完后一看标签和难度,咦,为什么没有lca的标签啊,为什么这个题的难度只有普及/提高减啊,这个不是和货车运输差不多的吗。。。

    于是愉快的交上去A掉了之后,仔细想了想新的做法,又想出两种做法:

    1.倍增lca+最小生成树:

    基本上同货车运输:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    void read(int &y)
    {
        y=0;char x=getchar();
        while(x<'0'||x>'9') x=getchar();
        while(x>='0'&&x<='9')
        {
            y=y*10+x-'0';
            x=getchar();
        }
    }
    struct edge
    {
        int u,v,w;
    }e[50005];
    bool cmp(edge x,edge y)
    {
        return x.w<y.w;
    }
    int fa[10005][25],maxw[10005][25];
    int f[10005],head[20005],nxt[20005],to[20005],d[20005],dep[10005];
    int n,m,s,t,cnt;
    int find(int x)
    {
        if(x==f[x]) return x;
        return f[x]=find(f[x]);
    }
    void add(int u,int v,int w)
    {
        to[cnt]=v;
        d[cnt]=w;
        nxt[cnt]=head[u];
        head[u]=cnt++;
    }
    void dfs(int x,int y)
    {
        for(int i=head[x];i!=-1;i=nxt[i])
        {
            if(i!=y)
            {
                dep[to[i]]=dep[x]+1;
                fa[to[i]][0]=x;
                maxw[to[i]][0]=d[i];
                dfs(to[i],i^1);
            }
        }
    }
    int lca(int x,int y)
    {
        if(dep[x]>dep[y])
        {
            int tmp=x;
            x=y;
            y=tmp;
        }
        int ans=-1;
        for(int i=15;i>=0;i--)
        {
            if(dep[fa[y][i]]>=dep[x])
            {
                ans=max(ans,maxw[y][i]);
                y=fa[y][i];
            }
        }
        if(x==y) return ans;
        for(int i=15;i>=0;i--)
        {
            if(fa[x][i]!=fa[y][i])
            {  
                ans=max(ans,max(maxw[x][i],maxw[y][i]));  
                x=fa[x][i];
                y=fa[y][i];
            }
        }
        return ans;
    }
    int main()
    {
        read(n);read(m);read(s);read(t);
        for(int i=0;i<m;i++)
        {
            read(e[i].u);read(e[i].v);read(e[i].w);
        }
        sort(e,e+m,cmp);
        memset(head,-1,sizeof(head));
        for(int i=1;i<=n;i++) f[i]=i;
        for(int i=0;i<m;i++)
        {
            if(find(e[i].u)!=find(e[i].v))
            {
                add(e[i].u,e[i].v,e[i].w);
                add(e[i].v,e[i].u,e[i].w);
                f[find(e[i].u)]=find(e[i].v);
            }
        }
        dep[1]=1,dfs(1,-1);
        for(int j=1;j<=15;j++)
        {
            for(int i=1;i<=n;i++)
            {
                fa[i][j]=fa[fa[i][j-1]][j-1];
                maxw[i][j]=max(maxw[i][j-1],maxw[fa[i][j-1]][j-1]);
            }
        }
        printf("%d",lca(s,t));
        return 0;
    }

    2.最小生成树+暴力公共祖先:

    此题只有一组数据,所以我们可以使用离线算法,首先求出图的最小生成树,然后由s节点暴力向上找父亲节点,一路标记,到达根节点后停止。在由t节点向上暴力找父亲节点,到达有标记的点之后停止。

    然后两点分别再向上到公共祖先,更新最大值,输出即可。

    3.最小生成树+巧妙利用并查集性质:

    继续使用离线算法,然后使用克鲁斯卡尔算法求最小生成树,当s与t在一个集合中时,s到t的路径就确定了,最长的边就是当前要处理的边,输出即可。

  • 相关阅读:
    小心SQL SERVER 2014新特性——基数评估引起一些性能问题
    SQL SERVER使用ODBC 驱动建立的链接服务器调用存储过程时参数不能为NULL值
    Windows Server 2012 Recycle Bin corrupted
    SQL SERVER CHAR ( integer_expression )各版本返回值差异的案例
    SQL Server 2008 R2 升级到 Service Pack 3后Report Builder启动不了
    MySQL如何导出带日期格式的文件
    ORACLE TO_CHAR函数格式化数字的出现空格的原因
    Linux监控工具介绍系列——smem
    Linux命令学习总结:dos2unix
    Linux命令学习总结:hexdump
  • 原文地址:https://www.cnblogs.com/zeroform/p/7582672.html
Copyright © 2020-2023  润新知