• hdu 2874 Connections between cities (离线LCA)


    给n顶点和m条边求任意两点的最短距离,只要找到他们的最近公共祖先就可以求出他们的最短距离,先处理后询问,只是很明显的离线LCA可以用tarjan离线算法。

    昨天做了一道类似的,此题和poj1330很接近,几乎是它的一个扩展。如果做个那题此题可迎刃而解。

    #include<iostream>
    #include<vector>
    using namespace std;
    const int N=10009;
    int father[N],anc[N],vis[N],r[N],dis[N],color[N];
    struct node
    {
        int v,w;
    };
    vector<node> point[N],Q[N];
    int ans[1000009];
    int n,q;
    int count;
    int find(int x)
    {
        int i,t;
        for(i=x;father[i]>0;i=father[i]);
        while(i!=x)//把所有子节点都指向根,
        {
            t=father[x];
            father[x]=i;
            x=t;
        }
        return i;
    }
    void Union(int a,int b)
    {
        int x=find(a);
        int y=find(b);
        if(x!=y)
        {
            if(r[x]<r[y])//安秩合并
            {
                father[x]=y;
                r[y]+=r[x];
            }
            else
            {
                father[y]=x;
                r[x]+=r[y];
            }
            
        }
    }
    void tarjan_lca(int u,int d)
    {
        anc[u]=u;
        vis[u]=1;
        int i;
        dis[u]=d;
        for(i=0;i<point[u].size();i++)
        {
            int v=point[u][i].v;
            if(!vis[v])
            {
                tarjan_lca(v,dis[u]+point[u][i].w);
                Union(u,v);
                anc[find(u)]=u;
            }
        }
        color[u]=count;
        for(i=0;i<Q[u].size();i++)//查询
        {
            int v=Q[u][i].v;
            if(color[v])
            {
                if(color[v]==count)//判断是否属于同一集合
                {
                    ans[Q[u][i].w]=dis[u]+dis[v]-2*dis[anc[find(v)]];
                }
                else
                    ans[Q[u][i].w]=-1;
            }
        }
    }
    void init()
    {
        for(int i=0;i<=n;i++)
        {
            father[i]=-1;
            vis[i]=0;
            anc[i]=0;
            r[i]=1;
            color[i]=0;
            point[i].clear();
            Q[i].clear();
        }
        memset(ans,-1,sizeof(ans));
    }
    int main()
    {
        int m,a,b,i,w;
        while(scanf("%d%d%d",&n,&m,&q)!=EOF)
        {
            init();
            for(i=0;i<m;i++)
            {
                scanf("%d%d%d",&a,&b,&w);
                node temp;
                temp.w=w;
                temp.v=b;
                point[a].push_back(temp);
                temp.v=a;
                point[b].push_back(temp);
            }
            for(i=0;i<q;i++)
            {
                scanf("%d%d",&a,&b);
                node temp;
                temp.v=b;
                temp.w=i;
                Q[a].push_back(temp);
                temp.v=a;
                Q[b].push_back(temp);
            }
            count=1;
            for(i=1;i<=n;i++)
            {
                if(!vis[i])
                {
                    tarjan_lca(i,0);
                    count++;
                }
            }
            for(i=0;i<q;i++)
            {
                if(ans[i]==-1)
                    printf("Not connected
    ");
                else
                    printf("%d
    ",ans[i]);
            }
        }
        return 0;
    }


    我其实对STL的容器不是很了解,所以刚开始准备用结构体数组,可是数组太多,怕超。所以用了vector容器,也好顺便学习一下容器

  • 相关阅读:
    蓝桥学院2019算法题1.8
    蓝桥学院2019算法题1.7
    蓝桥学院2019算法题1.6
    蓝桥学院2019算法题1.5
    蓝桥学院2019算法题1.4
    蓝桥学院2019算法题1.3
    一个简单java爬虫爬取网页中邮箱并保存
    轻松配置java开发环境
    PDF转word文档
    直接插入排序
  • 原文地址:https://www.cnblogs.com/BruceNoOne/p/3210172.html
Copyright © 2020-2023  润新知