• 网易有道笔试:求连通图的割点(关节点)


    题目:求一个连通图的割点,割点的定义是,如果除去此节点和与其相关的边,图不再连通,描述算法。

    分析:

    1. 最简单也是最直接的算法是,删除一个点然后判断连通性,如果删除此点,图不再连通,则此点是割点,反之不是割点(图的连通性一般通过深搜来判定,是否能一次搜索完 全部顶点);

    2. 通过深搜优先生成树来判定。从任一点出发深度优先遍历得到优先生成树,对于树中任一顶点V而言,其孩子节点为邻接点。由深度优先生成树可得出两类割点的特性:

         (1)若生成树的根有两棵或两棵以上的子树,则此根顶点必为割点。因为图中不存在连接不同子树顶点的边,若删除此节点,则树便成为森林;

         (2)若生成树中某个非叶子顶点V,其某棵子树的根和子树中的其他节点均没有指向V的祖先的回边,则V为割点。因为删去v,则其子树和图的其它部分被分割开来。

    仍然利用深搜算法,只不过在这里定义visited[v]表示为深度优先搜索遍历图时访问顶点v的次序号,定义low[v]=Min{visited[v],low[w],visited[k]},其中w是顶点v在深度优先生成树上的孩子节点;k是顶点v在深度优先生成树上由回边联结的祖先节点。

       割点判定条件:如果对于某个顶点v,存在孩子节点w且low[w]>=visited[v],则该顶点v必为关节点。因为当w是v的孩子节点时,low[w]>=visited[v],表明w及其子孙均无指向v的祖先的回边,那么当删除顶点v后,v的孩子节点将于其他节点被分割开来,从来形成新的连通分量。

    #include <iostream>
    #include <string>
    using namespace std;
    
    #define MAX_VERTEX_NUM 13
    
    //邻接表存储结构
    typedef struct ArcNode{
        int adjvex;
        ArcNode *nextarc;
    }ArcNode;
    
    typedef struct VNode{
        string data;
        ArcNode* firstarc;
    }VNode,AdjList[MAX_VERTEX_NUM];
    
    typedef struct{
        AdjList vertices;
        int vexnum, arcnum;
    }ALGraph;
    
    //返回u在图中的位置
    int LocateVex(ALGraph G, string u)
    {
        for(int i=0; i<G.vexnum; i++)
            if(G.vertices[i].data==u)
                return i;
        return -1;
    }
    
    //构造图
    void CreateDG(ALGraph &G)
    {
        string v1, v2;
        int i, j, k;
        cout<<"请输入顶点数和边数:";
        cin>>G.vexnum>>G.arcnum;
    
        cout<<"请输入顶点:";
        for(i=0; i<G.vexnum; i++)
        {
            cin>>G.vertices[i].data;
            G.vertices[i].firstarc=NULL;
        }
    
        cout<<"请输入边:"<<endl;
        for(k=0; k<G.arcnum; k++)
        {
            cin>>v1>>v2;
            i=LocateVex(G, v1);
            j=LocateVex(G, v2);
    
            //无向图
            ArcNode *arc=new ArcNode;
            arc->adjvex=j;
            arc->nextarc=G.vertices[i].firstarc;
            G.vertices[i].firstarc=arc;
    
            arc=new ArcNode;
            arc->adjvex=i;
            arc->nextarc=G.vertices[j].firstarc;
            G.vertices[j].firstarc=arc;
        }
    
    }
    
    //求割点
    int count ;
    int visited[MAX_VERTEX_NUM];
    int low[MAX_VERTEX_NUM];
    
    //从第v0个顶点出发深搜,查找并输出关节点(割点)
    void DFSArticul(ALGraph G, int v0)
    {
        int min, w;
        ArcNode *p;
        visited[v0]=min=++count;//v0是第count个访问的顶点,min的初值为visited[v0],即v0的访问次序
    
        for(p=G.vertices[v0].firstarc; p ; p=p->nextarc)
        {
            w=p->adjvex;
            if(visited[w]==0)//w未曾访问,是v0的孩子
            {
                DFSArticul(G, w);//从第w个顶点出发深搜,查找并输出关节点(割点),返回前求得low[w]
                if(low[w]<min)//如果v0的孩子节点w的low[]小,说明孩子节点还与其他节点(祖先)相邻
                    min=low[w];
                if(low[w]>=visited[v0])//v0的孩子节点w只与v0相连,则v0是关节点(割点)
                    cout<<G.vertices[v0].data<<" ";
            }
            else if(visited[w]<min)//w已访问,则w是v0生成树上祖先,它的访问顺序必小于min
                min=visited[w];
        }
    
        low[v0]=min;//low[v0]取三者最小值
        
    }
    
    void FindArticul(ALGraph G)
    {
        int i, v;
        ArcNode *p;
        count=1;
        visited[0]=1;//从0号节点开始
        for(i=1; i<G.vexnum; i++)
            visited[i]=0;
        p=G.vertices[0].firstarc;
        v=p->adjvex;
        DFSArticul(G, v);
        if(count<G.vexnum)
        {
            cout<<G.vertices[0].data<<" ";
            while(p->nextarc)
            {
                p=p->nextarc;
                v=p->adjvex;
                if(visited[v]==0)
                    DFSArticul(G, v);
            }
        }
    }
    
    void main()
    {
        ALGraph g;
        CreateDG(g);
    
        cout<<"割点如下: "<<endl;
        FindArticul(g);
        cout<<endl;
    }
  • 相关阅读:
    python之虚拟环境
    Django之auth模块
    Django之cookie/session
    前端构建工具gulp(2)-- 安装gulp-sass报错问题
    前端构建工具gulp(1)
    ebay api接口开发基本步骤
    华硕win10文档类文件点击右键时会闪一下,没法用右键打开文件
    oracle 12c 加入系统服务
    maven热部署到tomcat
    eclipse配置tomcat
  • 原文地址:https://www.cnblogs.com/wuchanming/p/3838475.html
Copyright © 2020-2023  润新知