zoukankan      html  css  js  c++  java
  • HDU2874 Connections between cities(并查集+倍增LCA算法求森林最短路)

    题意:

    第一次世界大战后,许多城市遭到严重破坏,我们需要重建这些城市。但是,某些材料只能在某些地方生产。所以我们需要将这些材料从一个城市运到另一个城市。由于战争期间大部分道路已被完全摧毁,两个城市之间可能没有路径,也没有环存在。 现在,你的任务来了。在告诉您道路状况后,我们想知道任何两个城市之间是否存在路径。如果答案是肯定的,则输出它们之间的最短路径。

    题解:

    并查集判连通块,对每个连通块做一个倍增LCA处理,之后就是求LCA算带边权树的最短路~

    #include<cstdio>
    #include<algorithm>
    #include<cstring> 
    using namespace std;
    typedef long long ll;
    const int maxn=1e5;
    int N,M,Q;
    int father[30][maxn];
    int h[maxn];
    ll d[maxn];
    struct node {
        int u;
        int v;
        ll w;
        int next;
    }edge[maxn];
    int head[maxn];
    int tol;
    void addedge (int u,int v,ll w) {
        edge[tol].u=u;
        edge[tol].v=v;
        edge[tol].w=w;
        edge[tol].next=head[u];
        head[u]=tol++;
    } 
    int visit[maxn];
    void dfs (int x,int u) {
        visit[x]=1;
        father[0][x]=u;
        for (int i=1;(1<<i)<=h[x];i++)
            father[i][x]=father[i-1][father[i-1][x]];
        for (int i=head[x];i!=-1;i=edge[i].next) {
            int v=edge[i].v;
            if (v==father[0][x]) continue;
            h[v]=h[x]+1;
            d[v]=d[x]+edge[i].w;
            dfs(v,x);
        }
    }
    int lca (int x,int y) {
        if (h[x]>h[y]) swap(x,y);
        for (int i=20;i>=0;i--)
            if (h[x]<=h[y]-(1<<i)) y=father[i][y];
        if (x==y) return x;
        for (int i=20;i>=0;i--) 
            if (father[i][x]!=father[i][y]) {
                x=father[i][x];
                y=father[i][y];
            } 
        return father[0][x];
    }
    ll getDis (int x,int y) {
        return d[x]+d[y]-2*d[lca(x,y)];
    }
    int f[maxn];
    int findfather (int x) {
        int a=x;
        while (x!=f[x]) x=f[x];
        while (a!=f[a]) {
            int z=a;
            a=f[a];
            f[z]=x;
        }
        return x;
    }
    void Union (int a,int b) {
        int faA=findfather(a);
        int faB=findfather(b);
        if (faA!=faB) f[faA]=faB;
    }
    int main () {
        while (~scanf("%d%d%d",&N,&M,&Q)) {
            memset(father,0,sizeof(father));
            memset(h,0,sizeof(h));
            memset(d,0,sizeof(d));
            memset(head,-1,sizeof(head));
            memset(visit,0,sizeof(visit));
            tol=0;
            for (int i=1;i<=N;i++) f[i]=i;
            for (int i=0;i<M;i++) {
                int u,v;ll w;
                scanf("%d%d%lld",&u,&v,&w);
                addedge(u,v,w);
                addedge(v,u,w);
                Union(u,v);
            }
            for (int i=1;i<=N;i++)
                if (!visit[i]) dfs(i,i);
            for (int i=0;i<Q;i++) {
                int x,y;
                scanf("%d%d",&x,&y);
                if (findfather(x)!=findfather(y)) 
                    printf("Not connected
    ");
                else 
                    printf("%lld
    ",getDis(x,y));
            }
        }
        return 0;
    }
  • 相关阅读:
    Android 之 JSON操作
    android 之 XMLPull
    DOM 之 SAX操作
    android之DOM生成与解析
    parseDouble()方法
    读取遥感图像中遇到的问题集锦
    xml学习
    linux基础
    hadoop的基本概念 伪分布式hadoop集群的安装 hdfs mapreduce的演示
    【原】自定义tableViewCell的两种方法
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/12526801.html
Copyright © 2011-2022 走看看