zoukankan      html  css  js  c++  java
  • 洛谷 P1967 货车运输 LCA + 最小生成树

     两点之间边权最大值的最小值一定在图的最小生成树中取到。

    求出最小生成树,进行倍增即可。

    Code:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn = 10000 + 3;
    const int maxm = 100000 + 3;
    const int inf  = 10000000+3;
    const int logn = 30;
    int st[maxm], ed[maxm], cost[maxm];
    int head[maxm],to[maxm<<1], nex[maxm<<1], val[maxm<<1], cnt;
    int F[maxn][logn], minv[maxn][logn], dep[maxn];
    int n,m;
    int cmp(int i,int j)
    {
        return cost[i] > cost[j];
    }
    struct Make_Tree
    {
        int A[maxm],p[maxn];
        int find(int x)
        {
            return p[x] == x ? x : p[x] = find(p[x]);
        }
        inline void add_edge(int u,int v,int c)
        {
            nex[++cnt] = head[u], head[u] = cnt, to[cnt] = v, val[cnt] = c;
        }
        inline void solve()
        {
            for(int i = 1;i <= m;++i)A[i] = i;
            for(int i = 1;i <= n;++i)p[i] = i;
            sort(A+1,A+1+m,cmp);
            for(int i = 1;i <= m;++i)
            {
                int cur = A[i];  
                int a = st[cur], b = ed[cur];
                int x = find(a);
                int y = find(b);
                if(x == y)continue;
                add_edge(a,b,cost[cur]);
                add_edge(b,a,cost[cur]);
                p[x] = y;
            }
        }
    }T;      
    void dfs(int u,int fa,int c,int deep)
    {
        F[u][0] = fa, minv[u][0] = c, dep[u] = deep;
        for(int v = head[u]; v ;v = nex[v])
            if(to[v] != fa){
                dfs(to[v],u,val[v],deep+1);
            }
    }
    inline int solve(int a,int b)
    {
        if(dep[a] > dep[b])swap(a,b);
        int ans = inf;
        if(dep[b] != dep[a])
        {
            for(int i =logn-1;i>=0;--i)
               if(dep[a] <= dep[F[b][i]])
                {
                   ans = min(ans,minv[b][i]);
                   b = F[b][i];
                }
        }
        if(a == b)return ans;
        for(int i = logn-1;i>=0;--i)
        if(F[a][i] != F[b][i]) 
        {
            ans = min(ans,min(minv[a][i],minv[b][i]));
            a = F[a][i], b = F[b][i];
        }
        ans = min(ans,min(minv[a][0],minv[b][0]));
        return ans;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;++i)
            scanf("%d%d%d",&st[i],&ed[i],&cost[i]);
        T.solve();
        for(int i = 1;i <= n;++i) 
            if(!dep[i])dfs(i,0,0,1);
        for(int i = 1;i < logn-1;++i)
            for(int j = 1;j <= n;++j)
            {
                minv[j][i] = min(minv[j][i-1], minv[F[j][i-1]][i-1]);
                F[j][i] = F[F[j][i-1]][i-1];
            }
        int asks;
        scanf("%d",&asks);
        for(int i = 1;i <= asks;++i)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            if(T.find(a) != T.find(b) || a>n|| b>n)printf("-1
    ");
            else printf("%d
    ",solve(a,b));
        }
        return 0;
    }
    

      

  • 相关阅读:
    js 实现自增长
    常用的js脚本验证
    Jquery 收集
    Jquery 常用操作搜集
    Jquery 点击绑定行 弹出详细页面
    Jquery 了解
    Html 标尺
    Editor Guidelines
    程序员需要做到
    jS 回车事件
  • 原文地址:https://www.cnblogs.com/guangheli/p/9845086.html
Copyright © 2011-2022 走看看