zoukankan      html  css  js  c++  java
  • Luogu P1967 【货车运输】题解

    一看到这道题,就想到了某次小生成树

    • 一般对于无向图且不是树的情况,求路径经过边的最小(最大)值且不考虑路径总长,通常考虑最小(最大)生成树

    由于求尽量通过边,最大生成树即可

    很愉快的,问题转换成了如何求树上两点间的边权最小值。

    • 对于树上路径问题,我们通常考虑倍增或树剖

    (但我太菜了,不会树剖)所以就用倍增代替了

    也就是kruskal(懒得打prim)+倍增lca 综合时间复杂度 (O)((mlog n))

    码风奇特的代码如下:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    inline int Min(int a,int b) {
        return a<b?a:b;
    }
    
    inline void swap(int &a,int &b) {
        a^=b^=a^=b;
    }
    
    int n,m;
    
    int f[10005];
    
    struct edge {
        int u,v,w;
    } e[100005];
    
    struct tree {
        int u[100005],v[100005],w[100005];
        int first[10005],next[100005];
        int tot=0;
        int addedge(int a,int b,int c) {
            ++tot;
            u[tot]=a,v[tot]=b,w[tot]=c;
            next[tot]=first[a];
            first[a]=tot;
        }
    } tr;
    
    int cmp(edge a,edge b) {
        return a.w>b.w;
    }
    
    int gf(int x) {
        if(x==f[x]) {
            return x;
        }
        f[x]=gf(f[x]);
        return f[x];
    }
    
    void merge(int a,int b) {
        int fa=gf(a);
        int fb=gf(b);
        if(fa!=fb) {
            f[fb]=fa;
        }
    }
    
    void kruskal() {
        for(int i=1; i<=n; i++) {
            f[i]=i;
        }
        for(int i=1; i<=m; i++) {
            if(gf(e[i].u)!=gf(e[i].v)) {
                merge(e[i].u,e[i].v);
                tr.addedge(e[i].u,e[i].v,e[i].w);
                tr.addedge(e[i].v,e[i].u,e[i].w);
            }
        }
    }
    
    int p[10005][25];
    int mp[10005][25];
    int dep[10005];
    
    int vis[10005];
    
    void dfs(int x) {
        vis[x]=1;
        for(int i=tr.first[x]; i; i=tr.next[i]) {
            if(!vis[tr.v[i]]) {
                p[tr.v[i]][0]=x;
                mp[tr.v[i]][0]=tr.w[i];
                dep[tr.v[i]]=dep[x]+1;
                dfs(tr.v[i]);
            }
        }
    }
    
    void init() {
        for(int i=1; i<=n; i++) {
            dfs(i);
        }
        for(int j=1; j<=20; j++) {
            for(int i=1; i<=n; i++) {
                p[i][j]=p[p[i][j-1]][j-1];
                mp[i][j]=Min(mp[i][j-1],mp[p[i][j-1]][j-1]);
            }
        }
    }
    
    int lca(int a,int b) {
        if(dep[a]<dep[b]) {
            swap(a,b);
        }
        for(int i=20; i>=0; i--) {
            if(dep[a]-(1<<i)>=dep[b]) {
                a=p[a][i];
            }
        }
        if(a==b) {
            return a;
        }
        for(int i=20; i>=0; i--) {
            if(p[a][i]!=p[b][i]) {
                a=p[a][i];
                b=p[b][i];
            }
        }
        return p[a][0];
    }
    
    int work(int a,int b) {
        int l=lca(a,b);
        int ans=1<<30;
        if(a!=l) {
            for(int i=20; i>=0; i--) {
                if(dep[p[a][i]]>dep[l]) {
                    ans=Min(ans,mp[a][i]);
                    a=p[a][i];
                }
            }
            ans=Min(ans,mp[a][0]);
        }
        if(b!=l) {
            for(int i=20; i>=0; i--) {
                if(dep[p[b][i]]>dep[l]) {
                    ans=Min(ans,mp[b][i]);
                    b=p[b][i];
                }
            }
            ans=Min(ans,mp[b][0]);
        }
        return ans;
    }
    
    int main() {
        scanf("%d%d",&n,&m);
        for(int i=1; i<=m; i++) {
            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        }
        sort(e+1,e+m+1,cmp);
        kruskal();
        init();
        int q;
        scanf("%d",&q);
        for(int i=1; i<=q; i++) {
            int a,b;
            scanf("%d%d",&a,&b);
            if(gf(a)!=gf(b)) {
                printf("-1
    ");
                continue;
            }
            printf("%d
    ",work(a,b));
        }
        return 0;
    }
    
  • 相关阅读:
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    Java实现 LeetCode 803 打砖块 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    Java实现 LeetCode 803 打砖块 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    英文标点
    post sharp 与log4net 结合使用,含执行源码 转拷
  • 原文地址:https://www.cnblogs.com/Railgunforever/p/9965817.html
Copyright © 2011-2022 走看看