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;
    }
    
  • 相关阅读:
    iOS开发>学无止境
    iOS开发>学无止境
    iOS开发>学无止境
    Objective-C学习—UITableView的使用
    iOS开发>学无止境
    iOS开发—AFNetworking的使用
    iOS开发>学无止境
    c#笔记(六)——数组(2)
    c#笔记(六)——数组
    c#笔记(五)——循环结构
  • 原文地址:https://www.cnblogs.com/Railgunforever/p/9965817.html
Copyright © 2011-2022 走看看