• P1967 货车运输


    emmmm一开始是想到网络流来着???(最大流嘛233)

    然后发现自己好像已经差不多忘完了???

    于是打开题解,ctrl+f,输入网络流,好像没有题解,于是就老老实实想正解去了。

    正解:

    多组询问,想想网络流也要T(EK本来就慢,其它就不说了),所以一定是还有更简单的方法的!!!

    对于每一个点(或者说路径),只有最小的那个边才对答案有影响(不是吗?)

    慢着!这不是.....最小生成树?

    于是就建最小生成树然后LCA。。。。。

    于是愉快地选择kruskal和倍增lca。

    于是这题就没什么了

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=500005;
    int m,n,fat[maxn];
    struct node
    {
        int x,y,z;
    }a[maxn];
    struct edge
    {
        int next,to,dis;
    }e[maxn<<1];
    int head[maxn],cnt,vis[maxn];
    inline void addedge(int from,int to,int dis)
    {
        e[++cnt].next=head[from];
        e[cnt].to=to;
        e[cnt].dis=dis;
        head[from]=cnt;
    }
    bool cmp(node x,node y)
    {
        return x.z>y.z;
    }
    int find(int x)
    {
        return fat[x]==x?x:fat[x]=find(fat[x]);
    }
    void kruskal()
    {
        for(int i=1;i<=n;i++)
        fat[i]=i;
        for(int i=1;i<m;i++)
        {
            int fa=find(a[i].x);
            int fb=find(a[i].y);
            if(fa!=fb)
            {
                fat[fa]=fb;
                addedge(a[i].x,a[i].y,a[i].z);
                addedge(a[i].y,a[i].x,a[i].z);
            }
        }
    }
    int dep[maxn],f[25][maxn],w[25][maxn];
    void dfs(int u,int deep)//预处理lca
    {
        vis[u]=1;
        dep[u]=deep;
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(dep[v]!=0)
            continue;
            dfs(v,deep+1);
            f[0][v]=u;
            w[0][v]=e[i].dis;
        }
    }
    int lca(int a,int b)//lca
    {
        if(find(a)!=find(b)) return -1;//不连通
        int ans=99999999;
        if(dep[a]<dep[b])
        swap(a,b);
        for(int i=20;i>=0;i--)
        {
            if(dep[b]<=dep[a]-(1<<i))
            {
                ans=min(ans,w[i][a]);
                a=f[i][a];
            }
        }
        if(a==b)
        return ans;
        for(int i=20;i>=0;i--)
        {
            if(f[i][a]!=f[i][b])
            {
                ans=min(ans,min(w[i][a],w[i][b]));
                a=f[i][a];
                b=f[i][b];
            }
        }
        ans=min(ans,min(w[0][a],w[0][b]));
        //printf("%d ",ans);
        return ans;
    }
    int main()
    {
        //freopen("testdata.in","r",stdin);
        //freopen("1.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
        sort(a+1,a+m+1,cmp);
        kruskal();
        for(int i=1;i<=n;i++)
        {
            if(vis[i])
            continue;
            dfs(i,1);
            f[0][i]=i;
            w[0][i]=99999999;
        }
        for(int i=1;(1<<i)<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                f[i][j]=f[i-1][f[i-1][j]];
                w[i][j]=min(w[i-1][j],w[i-1][f[i-1][j]]);
            }
        }
        int q;
        scanf("%d",&q);
        for(int i=1;i<=q;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d
    ",lca(x,y));
        }
        return 0;
    }

    (完)

  • 相关阅读:
    Win10 WSL Ubuntu18.04 编译安装MySQL5.7
    PHP7 深入理解
    php session 测试
    nginx 匹配路由分发php和golang
    composer 库无法提交git
    Win10 1803安装Ubuntu1804子系统
    dhtmlxTreeGrid使用
    win7 64位系统下安装PL/SQL连接Oracle服务器的解决方法
    转载--eclipse快捷键
    JUnit4学习笔记2-Eclipse中使用JUint4进行单元测试
  • 原文地址:https://www.cnblogs.com/ajmddzp/p/11349026.html
Copyright © 2020-2023  润新知