• hdu2586-How far away ?-(最近公共祖先-Tarjan离线算法)


    http://acm.hdu.edu.cn/showproblem.php?pid=2586

    题意:有n个点,有n-1条线连通,求两点间的最短距离,最近公共祖先的入门题。Tarjan离线算法。

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<math.h>
    #include<string>
    #include<queue>
    #define ll long long
    #define inf 0x3f3f3f3f
    using namespace std;
    int t;
    int n,m;
    int x,y,z;
    bool vis[40005];///深搜过程判断是否被搜过
    int par[40005];///存储节点的父亲
    int dis[40005];///任意一点到搜索起始点的距离
    int ans[205];
    
    struct node1
    {
        int to;
        int val;
    };
    vector<node1>edge[40005];///邻接表存储边
    
    struct node2
    {
        int to;
        int idx;///第几个查询
    };
    vector<node2>que[40004];///邻接表存储查询
    
    void init()
    {
        memset(dis,0,sizeof(dis));
        memset(vis,false,sizeof(vis));
        for(int i=1;i<=n;i++)
        {
            edge[i].clear();
            que[i].clear();
            par[i]=i;
        }
    }
    
    int find(int x)///并查集找爹
    {
        if(par[x]==x)
            return x;
        else
            return par[x]=find(par[x]);
    }
    
    void unit(int x,int y)///认x做父亲
    {
        x=find(x);
        y=find(y);
        if(x!=y)
            par[y]=x;
    }
    
    void dfs(int now,int w)///now是当前点,w是到起始点的距离
    {
        vis[now]=true;
        dis[now]=w;
        int len1=edge[now].size();
        for(int i=0;i<len1;i++)
        {
            int temp=edge[now][i].to;///临时存储邻接点,简洁表示
            if( !vis[ temp ] )
            {
                dfs( temp,w+edge[now][i].val );
                unit(now,temp);///搜完才更新父节点
            }
        }
    
        int len2=que[now].size();
        for(int i=0;i<len2;i++)///看一下有没有 与 当前点 有询问关系的点
        {
            int temp=que[now][i].to;
            if( vis[ temp ] )
            {
                ans[ que[now][i].idx ]  = dis[now]+dis[temp]-2*dis[ find(temp) ];
                ///两点的最短距离 = 两点到起点的距离之和 - 两倍公共祖先到起点的距离
            }
        }
    }
    
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d %d",&n,&m);
            init();
            for(int i=1;i<n;i++)
            {
                scanf("%d%d%d",&x,&y,&z);
                edge[x].push_back( {y,z} );
                edge[y].push_back( {x,z} );
            }
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&x,&y);
                que[x].push_back( {y,i} );
                que[y].push_back( {x,i} );
            }
            dfs(1,0);///以1为起始点深搜
            for(int i=1;i<=m;i++)
                printf("%d
    ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    学习前先认识一下MVC
    关于C#问号(?)的三个用处
    MVC上传图片示例
    在html中控制自动换行
    mvc中viewdata 和viewbag的区别
    eclipse 下找不到或无法加载主类的解决办法
    js实现checkbox全选与反选
    web组件新学--layer
    获取注册表最高权限
    pstools使用教程
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/10783254.html
Copyright © 2020-2023  润新知