• 1021. Deepest Root (25)——DFS+并查集


    http://pat.zju.edu.cn/contests/pat-a-practise/1021

    无环连通图也可以视为一棵树,选定图中任意一点作为根,如果这时候整个树的深度最大,则称其为 deepest root。 给定一个图,按升序输出所有 deepest root。如果给定的图有多个连通分量,则输出连通分量的数量。

    1.使用并查集判断图是否为连通的。

    2.任意选取一点,做 dfs 搜索,选取其中一个最远距离的点 A,再做一次 dfs,找到的所有距离最远的点以及点 A 都是 deepest root。

    考虑到为稀疏图,则使用动态链表

    #include<stdio.h>
    #include<stack>
    #include<iostream>
    #include<vector>
    #include<set>
    #include<queue>
    using namespace std;
    
    vector<int> map[10099]; 
    int f[10099];
    int find(int k){
        if(f[k]==-1)return k;
        else
            return f[k]=find(f[k]);
    }
    
    int um(int a,int b){
        int fa,fb;
        fa=find(a);
        fb=find(b);
    
        if(fa==fb)return 0;//表示有环
    
        if(fa!=fb)
            f[fa]=fb;
        return 1;
    }
    
    int step[10099];
    
    void dfs(int x,int STEP){
        
        int i;
        for(i=0;i<map[x].size();i++){
            if(step[map[x][i]]!=0)continue;
            step[map[x][i]]=STEP;
            dfs(map[x][i],STEP+1);
        }
    }
    
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF){
            int i,a,b;
            
            for(i=0;i<=n;i++){
                f[i]=-1;
                step[i]=0;
            }
    
            int huan=0;
            for(i=1;i<n;i++){
                scanf("%d%d",&a,&b);
                if(um(a,b)==0)huan=1;
    
                map[a].push_back(b);
                map[b].push_back(a);
            }
            int connectAdd=0;
            set<int>set1;
            int ttemp;
            for(i=1;i<=n;i++){
                ttemp=find(i);
                set1.insert(ttemp);
            }
    
            if(set1.size()>=2||huan==1){
                printf("Error: %d components
    ",set1.size());continue;
            }
            step[1]=1;
            dfs(1,2);
    
            int max=0,ri;
            for(i=1;i<=n;i++){
                if(max<step[i]){
                    max=step[i];
                    ri=i;
                }
            }
    
            for(i=1;i<=n;i++){
                step[i]=0;
            }
            step[ri]=1;
            dfs(ri,2);
    
            max=0;
            for(i=1;i<=n;i++){
                if(max<step[i]){
                    max=step[i];
                }
            }
    
            for(i=1;i<=n;i++){
                if(step[i]==max||step[i]==1){
                    printf("%d
    ",i);
                }
            }
        }
        
        return 0;
    }
    View Code

    其实上面的算法还有点问题,虽然AC了

    考虑 

    5
    1 2
    1 3
    2 4
    2 5

    应该是输出

    3

    4

    5

    算法改进 以(第2次dfs最深的点)为起点,再做DFS得到的最深的点,这些点才是所有最深的点

    #include<stdio.h>
    #include<stack>
    #include<iostream>
    #include<vector>
    #include<set>
    #include<queue>
    using namespace std;
    
    vector<int> map[10099]; 
    int f[10099];
    int find(int k){
        if(f[k]==-1)return k;
        else
            return f[k]=find(f[k]);
    }
    
    int um(int a,int b){
        int fa,fb;
        fa=find(a);
        fb=find(b);
    
        if(fa==fb)return 0;//表示有环
    
        if(fa!=fb)
            f[fa]=fb;
        return 1;
    }
    
    int step[10099];
    int deepF[10099];//第2次dfs最深的点
    int deepR[10099];//以(第2次dfs最深的点)为起点,做DFS得到的最深的点
    
    void dfs(int x,int STEP){
        
        int i;
        for(i=0;i<map[x].size();i++){
            if(step[map[x][i]]!=0)continue;
            step[map[x][i]]=STEP;
            dfs(map[x][i],STEP+1);
        }
    }
    
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF){
            int i,a,b,j;
            
            for(i=0;i<=n;i++){
                f[i]=-1;
                step[i]=0;
                deepF[i]=0;
                deepR[i]=0;
            }
    
            int huan=0;
            for(i=1;i<n;i++){
                scanf("%d%d",&a,&b);
                if(um(a,b)==0)huan=1;
    
                map[a].push_back(b);
                map[b].push_back(a);
            }
            int connectAdd=0;
            set<int>set1;
            int ttemp;
            for(i=1;i<=n;i++){
                ttemp=find(i);
                set1.insert(ttemp);
            }
    
            if(set1.size()>=2||huan==1){
                printf("Error: %d components
    ",set1.size());continue;
            }
            step[1]=1;
            dfs(1,2);
    
            int max=0,ri;
            for(i=1;i<=n;i++){
                if(max<step[i]){
                    max=step[i];
                    ri=i;
                }
            }
    
            for(i=1;i<=n;i++){
                step[i]=0;
            }
            step[ri]=1;
            dfs(ri,2);
    
            max=0;
            for(i=1;i<=n;i++){
                if(max<step[i]){
                    max=step[i];
                }
            }
    
            for(i=1;i<=n;i++){
                if(step[i]==max||step[i]==1){
                    //printf("%d
    ",i);
                    deepF[i]=1;
                    deepR[i]=1;
                }
            }
    
            for(i=1;i<=n;i++){
                if(deepF[i]==0)continue;
                for(j=1;j<=n;j++)step[j]=0;
    
                dfs(i,2);
                for(j=1;j<=n;j++){
                    if(step[j]==max)deepR[j]=1;
                }
            }
    
            for(i=1;i<=n;i++){
                if(deepR[i]==1)printf("%d
    ",i);
            }
        }
        
        return 0;
    }
    View Code
  • 相关阅读:
    用简单C程序分析DOS下的EXE文件【转】
    汇编函数的调用[转自KingofCoders]
    windows下的shellcode剖析浅谈[转自看雪]
    如何写一个简单的病毒程序[转]
    不用注册访问论坛技巧
    函数调用堆栈变化分析[转自看雪]
    IT学生解惑真经(下载)
    Windows 汇编语言编程教程[转]
    ESP定律介绍(转自看雪论坛贴)
    【Anti Virus专题】1.1 病毒的原理 [转自看雪]
  • 原文地址:https://www.cnblogs.com/huhuuu/p/3323326.html
Copyright © 2020-2023  润新知