zoukankan      html  css  js  c++  java
  • HDU2874【倍增、ST】

    题目链接【https://vjudge.net/problem/HDU-2874】

    题意: 输入一个森林,总节点不超过N(N<10000),由C次询问(C<1000000),每次询问两个点,如果来联通输出,两点之间的距离,如果不来联通,输出“Not connected”;

    思路:首先判断u,v两个点在不在同一个树上,用并查集来做,如果在,就求两者的LCA,输入距离dis[u->v]=dis[u]+dis[v]-2*dis[LCA(u,v)]。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn = 10050;
    int N, M, C;
    struct node
    {
        int id, next, len;
    } E[maxn << 1];
    int head[maxn << 1], num;
    void initlist()
    {
        memset(head, -1, sizeof(head));
        num = 0;
    }
    void adde(int u, int v, int len)
    {
        E[num].id = u;
        E[num].len = len;
        E[num].next = head[v];
        head[v] = num++;
    }
    //----------------------------------------邻接表
    int fa[maxn<<1];
    void initfa()
    {
        for(int i = 0; i <= N; i++)
            fa[i] = i;
    }
    int Find(int id)
    {
        if(id == fa[id]) return id;
        else return fa[id] = Find(fa[id]);
    }
    void addu(int u, int v)
    {
        int x = Find(u);
        int y = Find(v);
        if(x != y)    fa[x] = y;
    }
    //----------------------------------------并查集
    int p[16][maxn], dep[maxn], dis[maxn], vis[maxn];
    void DFS(int u, int FA)
    {
        vis[u] = 1;
        for(int l = head[u]; l != -1; l = E[l].next)
        {
            int id = E[l].id;
            if(id == FA||vis[id]) continue;
            dep[id] = dep[u] + 1;
            dis[id] = dis[u] + E[l].len;
            p[0][id] = u;
            DFS(id, u);
        }
    }
    void initlca()
    {
        memset(p, -1, sizeof(p));
        memset(dep,0,sizeof(dep));
        memset(dis, 0, sizeof(dis));
        memset(vis, 0, sizeof(vis));
        for(int i = 1; i <= N; i++)
        {
            if(!vis[i])
                DFS(i, -1);
        }
        for(int k = 0; k + 1 <= 15; k++)
            for(int u = 1; u <= N; u++)
            {
                if(p[k][u] < 0) p[k + 1][u] = -1;
                else
                    p[k + 1][u] = p[k][p[k][u]];
            }
    }
    int LCA(int u, int v)
    {
        if(dep[u] > dep[v]) swap(u, v);
        for(int k = 0; k <= 15; k++)
        {
            if((dep[v] - dep[u]) >> k & 1)
                v = p[k][v];
        }
        if(u == v) return u;
        for(int k = 15; k >= 0; k--)
        {
            if(p[k][u] != p[k][v])
            {
                u = p[k][u];
                v = p[k][v];
            }
        }
        return p[0][u];
    }
    //----------------------------------------LCA
    int main ()
    {
        while(~scanf("%d%d%d", &N, &M, &C))
        {
            initlist();
            initfa();
            int u, v, ds;
            for(int i = 1; i <= M; i++)
            {
                scanf("%d%d%d", &u, &v, &ds);
                adde(u, v, ds);
                adde(v, u, ds);
                addu(u, v);
            }
            initlca();
            for(int i=1;i<=C;i++)
            {
                scanf("%d%d",&u,&v);
                int x=Find(u);
                int y=Find(v);
                if(x==y)
                {
                    printf("%d
    ",dis[u]+dis[v]-2*dis[LCA(u,v)]);
                }
                else
                    printf("Not connected
    ");
            }
        }
        return 0;
    }
    //#include<bits/stdc++.h>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int MAXN = 100050;
    //---------------------------------//邻接表
    struct node
    {
        int to, len, next;
    } E[MAXN * 2];
    int p[MAXN * 2], tot;
    void init()
    {
        memset(p, -1, sizeof(p));
        tot = 0;
    }
    void add(int u, int v, int len)
    {
        E[tot].to = v;
        E[tot].len = len;
        E[tot].next = p[u];
        p[u] = tot++;
    }
    //---------------------------------//并查集
    int fa[MAXN * 2];
    void init2(int n)
    {
        for(int i = 1; i <= n; i++)
            fa[i] = i;
    }
    int Find(int x)
    {
        if(x == fa[x])
            return fa[x];
        else
            return fa[x] = Find(fa[x]);
    }
    void join (int i, int j)
    {
        int x = Find(i);
        int y = Find(j);
        if(x != y) fa[y] = x;
    }
    //----------------------------------//LAC
    int ver[MAXN * 2], vis[MAXN], fst[MAXN], R[MAXN * 2];
    int dis[MAXN], KT[MAXN * 2], dp[MAXN * 2][25];
    void init3()
    {
        memset(vis, 0, sizeof(vis));
        tot = 0;
    }
    void DFS(int u, int dep, int len)
    {
        vis[u] = 1;
        ver[++tot] = u;
        R[tot] = dep;
        fst[u] = tot;
        dis[u] = len;
        for(int k = p[u]; k != -1; k = E[k].next)
        {
            int v = E[k].to;
            if(vis[v]) continue;
            DFS(v, dep + 1, len + E[k].len);
            ver[++tot] = u;
            R[tot] = dep;
        }
    }
    void ST(int n)
    {
        KT[1] = 0;
        for(int i = 2; i <= n; i++)
            KT[i] = KT[i / 2] + 1;
        for(int i = 1; i <= n; i++)
            dp[i][0] = i;
        for(int j = 1; j <= KT[n]; j++)
            for(int i = 1; i + (1 << j) - 1 <= n; i++)
            {
                int x = dp[i][j - 1];
                int y = dp[i + (1 << (j - 1))][j - 1];
                dp[i][j] = R[x] < R[y] ? x : y;
            }
    }
    int RMQ(int l, int r)
    {
        int k = KT[r - l + 1];
        int x = dp[l][k];
        int y = dp[r - (1 << k) + 1][k];
        return R[x] < R[y] ? x : y;
    }
    int LCA(int u, int v)
    {
        int l = fst[u], r = fst[v];
        if(l > r) swap(l, r);
        int t = RMQ(l, r);
        return ver[t];
    }
    //-------------------------------------//主函数
    int N, M, C;
    int main ()
    {
        while(~scanf("%d%d%d", &N, &M, &C))
        {
            init();//
            init2(N);
            int u, v, len;
            for(int i = 1; i <= M; i++)
            {
                scanf("%d%d%d", &u, &v, &len);
                add(u, v, len);
                add(v, u, len);
                join(u, v);
            }
            init3();
            for(int i = 1; i <= N; i++)
            {
                if(vis[i]) continue;
                DFS(i, 1, 0);
            }
            ST(2 * N - 1);
            for(int i = 1; i <= C; i++)
            {
                scanf("%d%d", &u, &v);
                int x = Find(u);
                int y = Find(v);
                if(x != y)
                {
                    printf("Not connected
    ");
                    continue;
                }
                int lca = LCA(u, v);
                printf("%d
    ", dis[u] + dis[v] - 2 * dis[lca]);
            }
        }
        return 0;
    }
    想的太多,做的太少。
  • 相关阅读:
    从句分析
    artDialog ( v 6.0.2 ) content 参数引入页面 html 内容
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 11 盛最多水的容器
    Java实现 LeetCode 11 盛最多水的容器
  • 原文地址:https://www.cnblogs.com/pealicx/p/6396961.html
Copyright © 2011-2022 走看看