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


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

    分析:

    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的孩子节点将于其他节点被分割开来,从来形成新的连通分量。

    1. #include <iostream>  
    2. #include <string>  
    3. using namespace std;  
    4.   
    5. #define MAX_VERTEX_NUM 13  
    6.   
    7. //邻接表存储结构  
    8. typedef struct ArcNode{  
    9.     int adjvex;  
    10.     ArcNode *nextarc;  
    11. }ArcNode;  
    12.   
    13. typedef struct VNode{  
    14.     string data;  
    15.     ArcNode* firstarc;  
    16. }VNode,AdjList[MAX_VERTEX_NUM];  
    17.   
    18. typedef struct{  
    19.     AdjList vertices;  
    20.     int vexnum, arcnum;  
    21. }ALGraph;  
    22.   
    23. //返回u在图中的位置  
    24. int LocateVex(ALGraph G, string u)  
    25. {  
    26.     for(int i=0; i<G.vexnum; i++)  
    27.         if(G.vertices[i].data==u)  
    28.             return i;  
    29.     return -1;  
    30. }  
    31.   
    32. //构造图  
    33. void CreateDG(ALGraph &G)  
    34. {  
    35.     string v1, v2;  
    36.     int i, j, k;  
    37.     cout<<"请输入顶点数和边数:";  
    38.     cin>>G.vexnum>>G.arcnum;  
    39.   
    40.     cout<<"请输入顶点:";  
    41.     for(i=0; i<G.vexnum; i++)  
    42.     {  
    43.         cin>>G.vertices[i].data;  
    44.         G.vertices[i].firstarc=NULL;  
    45.     }  
    46.   
    47.     cout<<"请输入边:"<<endl;  
    48.     for(k=0; k<G.arcnum; k++)  
    49.     {  
    50.         cin>>v1>>v2;  
    51.         i=LocateVex(G, v1);  
    52.         j=LocateVex(G, v2);  
    53.   
    54.         //无向图  
    55.         ArcNode *arc=new ArcNode;  
    56.         arc->adjvex=j;  
    57.         arc->nextarc=G.vertices[i].firstarc;  
    58.         G.vertices[i].firstarc=arc;  
    59.   
    60.         arc=new ArcNode;  
    61.         arc->adjvex=i;  
    62.         arc->nextarc=G.vertices[j].firstarc;  
    63.         G.vertices[j].firstarc=arc;  
    64.     }  
    65.   
    66. }  
    67.   
    68. //求割点  
    69. int count ;  
    70. int visited[MAX_VERTEX_NUM];  
    71. int low[MAX_VERTEX_NUM];  
    72.   
    73. //从第v0个顶点出发深搜,查找并输出关节点(割点)  
    74. void DFSArticul(ALGraph G, int v0)  
    75. {  
    76.     int min, w;  
    77.     ArcNode *p;  
    78.     visited[v0]=min=++count;//v0是第count个访问的顶点,min的初值为visited[v0],即v0的访问次序  
    79.   
    80.     for(p=G.vertices[v0].firstarc; p ; p=p->nextarc)  
    81.     {  
    82.         w=p->adjvex;  
    83.         if(visited[w]==0)//w未曾访问,是v0的孩子  
    84.         {  
    85.             DFSArticul(G, w);//从第w个顶点出发深搜,查找并输出关节点(割点),返回前求得low[w]  
    86.             if(low[w]<min)//如果v0的孩子节点w的low[]小,说明孩子节点还与其他节点(祖先)相邻  
    87.                 min=low[w];  
    88.             if(low[w]>=visited[v0])//v0的孩子节点w只与v0相连,则v0是关节点(割点)  
    89.                 cout<<G.vertices[v0].data<<" ";  
    90.         }  
    91.         else if(visited[w]<min)//w已访问,则w是v0生成树上祖先,它的访问顺序必小于min  
    92.             min=visited[w];  
    93.     }  
    94.   
    95.     low[v0]=min;//low[v0]取三者最小值  
    96.       
    97. }  
    98.   
    99. void FindArticul(ALGraph G)  
    100. {  
    101.     int i, v;  
    102.     ArcNode *p;  
    103.     count=1;  
    104.     visited[0]=1;//从0号节点开始  
    105.     for(i=1; i<G.vexnum; i++)  
    106.         visited[i]=0;  
    107.     p=G.vertices[0].firstarc;  
    108.     v=p->adjvex;  
    109.     DFSArticul(G, v);  
    110.     if(count<G.vexnum)  
    111.     {  
    112.         cout<<G.vertices[0].data<<" ";  
    113.         while(p->nextarc)  
    114.         {  
    115.             p=p->nextarc;  
    116.             v=p->adjvex;  
    117.             if(visited[v]==0)  
    118.                 DFSArticul(G, v);  
    119.         }  
    120.     }  
    121. }  
    122.   
    123. void main()  
    124. {  
    125.     ALGraph g;  
    126.     CreateDG(g);  
    127.   
    128.     cout<<"割点如下: "<<endl;  
    129.     FindArticul(g);  
    130.     cout<<endl;  
    131. }  


  • 相关阅读:
    转:CRF++
    ProBase
    图形数据库 Neo4j 开发实战
    Linux 下升级python和安装pip
    TensorFlow (RNN)深度学习 双向LSTM(BiLSTM)+CRF 实现 sequence labeling 序列标注问题 源码下载
    开源项目kcws代码分析--基于深度学习的分词技术
    文本情感分类(二):深度学习模型
    文本情感分类(一):传统模型
    重要博文
    LSTM 文本情感分析/序列分类 Keras
  • 原文地址:https://www.cnblogs.com/mfryf/p/2652102.html
Copyright © 2020-2023  润新知