zoukankan      html  css  js  c++  java
  • Luogu P1967 货车运输

    qwq

    这题是知道了正解做法才写的..

    求每两点间最小权值最大的路径,本来我以为要每个点都跑一遍dij(?),后来意识到生成树好像是用来找这个的( ´▽`)

    然后我问dtxdalao对不对,他说“我记得这道题好像要用倍增”(我:???剧透会被关进小黑屋的)

    其实就是最大生成树是随便建的,然后对于每两点,用倍增求他们的lca,沿途更新最小的边权即为答案

    其实我也没怎么debug i--这种问题就不说了吧)

    这题思路还算比较清晰,明白做法之后就分别把几个算法写出来就行了,

    注意:lca中最小边权的更新可能在跳到深度相同/同时倍增/最后求lca的路上,所以...反正多更新几次就没错啦w

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define MogeKo qwq
    using namespace std;
    const int maxn = 100005;
    int n,m,q,x,y;
    int cnt,head[maxn],to[maxn],nxt[maxn],val[maxn];
    int fa[maxn],dpth[maxn],p[maxn][25],w[maxn][25];
    
    void add(int x,int y,int z) {
        to[++cnt] = y;
        nxt[cnt] = head[x];
        head[x] = cnt;
        val[cnt] = z;
    }
    
    struct edg {
        int l,r,c;
    } a[maxn];
    
    bool cmp(edg A,edg B) {
        return A.c > B.c;
    }
    
    int getfa(int x) {
        if(fa[x] == x)return x;
        else return fa[x] = getfa(fa[x]);
    }
    
    void kruskal() {
        sort(a+1,a+m+1,cmp);
        for(int i = 1; i <= m; i++) {
            int xx = getfa(a[i].l);
            int yy = getfa(a[i].r);
            if(xx == yy)continue;
            fa[xx] = yy;
            add(xx,yy,a[i].c);
            add(yy,xx,a[i].c);
        }
    }
    
    void dfs(int u,int fa) {
        for(int i = 1; (1 << i) <= dpth[u]; i++) {
            p[u][i] = p[p[u][i-1]][i-1];
            w[u][i] = min(w[u][i-1],w[p[u][i-1]][i-1]);
        }
        for(int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if(v == fa)continue;
            dpth[v] = dpth[u]+1;
            p[v][0] = u;
            w[v][0] = val[i];
            dfs(v,u);
        }
    }
    
    int lca(int a,int b) {
        int ans = 2147483647;
        if(dpth[a] < dpth[b])
            swap(a,b);
        for(int i = log2(dpth[a]); i >= 0; i--)
            if(dpth[p[a][i]] >= dpth[b]) {
                ans = min(ans,w[a][i]);
                a = p[a][i];
            }
        if(a == b)return ans;
        for(int i = log2(dpth[a]); i >= 0; i--)
            if(p[a][i] != p[b][i]) {
                ans = min(ans,min(w[a][i],w[b][i]));
                a = p[a][i];
                b = p[b][i];
            }
        ans = min(ans,min(w[a][0],w[b][0]));
        return ans;
    }
    
    int main() {
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= n; i++)
            fa[i] = i;
        for(int i = 1; i <= m; i++)
            scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].c);
        kruskal();
        for(int i = 1; i <= n; i++)
            if(fa[i] == i){
                dpth[i] = 1;
                dfs(i,0);
            }
        scanf("%d",&q);
        while(q--) {
            scanf("%d%d",&x,&y);
            int xx = getfa(x);
            int yy = getfa(y);
            if(xx != yy) {
                printf("-1
    ");
                continue;
            }
            printf("%d
    ",lca(x,y));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ubuntu远程windows桌面
    spring boot 给返回值加状态 BaseData
    spring boot 拦截异常 统一处理
    IntelliJ IDEA spring boot 远程Ddbug调试
    IntelliJ IDEA 常用插件
    spring boot 请求地址带有.json 兼容处理
    spring boot 接口返回值去掉为null的字段
    spring boot 集成disconf
    Spring boot 自定义拦截器
    Linux下安装MySQL
  • 原文地址:https://www.cnblogs.com/mogeko/p/10354440.html
Copyright © 2011-2022 走看看