zoukankan      html  css  js  c++  java
  • HDU2874 Connections between cities 最近公共祖先

          

          第一次按常规的方法求,将所有的查询的u,v,和最近公共祖先都保存起来,然后用tarjan+并查集求最近公共祖先。因为询问的次数过多,所以在保存查询的时候总是MLE,后来参考了一下别人的代码,才突然觉悟,可以先将u,v,和其最近公共祖先保存到数组,然后再求结果,为什么不能直接保存其结果了。如果只保存结果的话,保存查询操作就可以节约1/3的内存,所以基本可以过了。

    代码如下:

       方法一:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const  int maxn = 10100;
    vector<pair<int,int> >tree[maxn],query[maxn];
    int father[2][maxn],res[1000010],dis[maxn],vis[maxn];
    
    void init(int n)
    {
        memset(vis,0,sizeof(vis));
        memset(dis,0,sizeof(dis));
        memset(res,-1,sizeof(res));
        for( int i = 0; i <= n; i++){
            tree[i].clear();
            query[i].clear();
            father[0][i] = father[1][i] = i;
        }
    }
    int find(int x,int k){
        if( x != father[k][x])
        return father[k][x] = find(father[k][x],k);
        return father[k][x];
    }
    void LCA(int u){
        vis[u] = 1;
    
        pair<int,int>x;
        int i,size = query[u].size();
        for(  i = 0; i < size; i++){
            x = query[u][i];
            if( vis[x.first])
               res[x.second] = dis[u] + dis[x.first] - 2*dis[find(x.first,0)];
        }
    
        size = tree[u].size();
        for( i = 0; i < size; i++){
            x = tree[u][i];
            if( !vis[x.first] ){
                dis[x.first] = dis[u] + x.second;
                LCA(x.first);
                union_set(x.first,u,0);
            }
        }
    }
    void union_set(int x,int y,int k){
        x = find(x,k);
        y = find(y,k);
        if ( x != y)
            father[k][x] = father[k][y];
    }
    int main()
    {
        int n,m,c;
        int u,v,d;
    	int i;
     //  freopen("in.txt","r",stdin);
        while( ~scanf("%d%d%d",&n,&m,&c) ){
            init(n);
            while( m-- ){
                scanf("%d%d%d",&u,&v,&d);
                union_set(u,v);
                tree[u].push_back(make_pair(v,d));
                tree[v].push_back(make_pair(u,d));
            }
            for( i = 0; i < c; i++){
                scanf("%d%d",&u,&v);
                if( find(u,1) != find(v,1))continue;
                query[u].push_back(make_pair(v,i));
                query[v].push_back(make_pair(u,i));
            }
            for(  i = 1; i <= n; i++){
                if( !vis[i] )
                    LCA(i);
            }
            for( i = 0; i < c; i++)
                if( res[i] == -1)puts("Not connected");
                else printf("%d
    ",res[i]);
        }
        return 0;
    }
    


     方法二:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    const int maxn = 10100;
    int anc[maxn],dis[maxn],deep[maxn],vis[maxn],fa[maxn];
    vector<pair<int,int> >tree[maxn];
    void init(int n)
    {
        memset(vis,0,sizeof(vis));
        for( int i = 1; i <= n; i++){
    		fa[i] = i;
            tree[i].clear();
        }
    }
    void dfs(int u,int now_fa,int now_anc,int now_deep,int now_len)
    {
    	fa[u] = now_fa;
    	anc[u] = now_anc;
        vis[u] = u;
        deep[u] = now_deep;
        dis[u] = now_len;
        for( int i = 0; i < tree[u].size() ; i++)
        {
            pair<int,int>x = tree[u][i];
            if( !vis[x.first] )
                dfs(x.first,u,now_anc,now_deep+1,now_len+x.second);
        }
    }
    int find(int x,int y){
        if( x == y)return x;
        if( deep[x] > deep[y])
        return find(fa[x],y);
        else return find(x,fa[y]);
    }
    int main()
    {
        int n,m,c;
        int u,v,d;
    	int i;
        while( ~scanf("%d%d%d",&n,&m,&c)){
    		init(n);
    
            while( m-- ){
                scanf("%d%d%d",&u,&v,&d);
                tree[u].push_back(make_pair(v,d));
                tree[v].push_back(make_pair(u,d));
            }
            for( i = 1; i <= n; i++ )
                if(!vis[i])
                    dfs(i,-1,i,0,0);
            for( i = 0; i < c; i++){
                scanf("%d%d",&u,&v);
                if(anc[u] != anc[v])puts("Not connected");
                else printf("%d
    ",dis[u]+dis[v] - 2*dis[find(u,v)]);
            }
        }
        return 0;
    }
    


     

  • 相关阅读:
    PowerDesigner15在win7-64位系统下对MySQL反向工程
    像竹子一样有节操
    spring 注解
    如何实现在已有代码之后添加逻辑之java动态代理
    如何实现在已有代码之后添加逻辑之继承,组合(静态代理)实现方法
    MySql按周,按月,按日分组统计数据
    SpringBoot 获取前端传递Json的几种方法
    Spring boot 基础整理(一)
    layui常用插件(二) 时间插件
    layui常用插件(一) 轮播图
  • 原文地址:https://www.cnblogs.com/LUO257316/p/3220800.html
Copyright © 2011-2022 走看看