• 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
  • 相关阅读:
    【转】adb push&pull bug --- Permission denied----不错
    【转】notepad++设置字体和字体大小
    【转】 Ubuntu下配置USB转串口及串口工具配置--不错
    【转】 ubuntu下fastboot找不到devices
    【转】ubuntu下安装及设置FTP服务器!!
    【转】vsftp 遇到错误 500 OOPS: vsftpd: refusing to run with writable root inside chroot()--不错
    【转】ubuntu安装ftp服务器
    android网址
    【转】Linux下Android ADB驱动安装详解
    【转】(总结)Linux下su与su -命令的本质区别
  • 原文地址:https://www.cnblogs.com/mogeko/p/10354440.html
Copyright © 2020-2023  润新知