• 点双连通分量的求解


    //点双连通分量的求解
    //就是通过tarjan算法求出关节点时,与关节点的子树就是一个连通分量,可以通过画图得到
    //所以可以将与顶点u有关的边放到栈中,然后一但满足low[v]>=dfn[u](表面点u是割点)(注释:由于dfs,已经建好了u
    //的子树,所以栈中有顶点u的子树),就可以进行退栈,直到遇到与u相关的边(由于dfs原因,之前的边都已经存入栈中
    //所以第一个(u,v)边是最后一个退栈的,所以到其为止即可。)由于让访问过的边map[u][v]=map[v][u]=2,所以之前访问
    //过的边不会再被访问。在dfs生成树图中能够很明显看出,就是关节点未被访问过的子树。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stack>
     4 using namespace std;
     5 int min(int x,int y)
     6 {
     7     return x<y?x:y;
     8 }
     9 
    10 int map[100][100],vis[100],dfn[100],depth,low[100],n,m;
    11 void init()
    12 {
    13     int i,j;
    14     memset(vis,0,sizeof(vis));
    15     vis[1]=1;
    16     low[1]=dfn[1]=1;
    17     depth=1;
    18 }
    19 struct edge
    20 {
    21     int x;
    22     int y;
    23 };
    24 stack<edge>s;
    25 void dfs(int u)
    26 {
    27     int i,j;
    28     for(i=1;i<=n;i++)
    29     {
    30         if(map[u][i]==1)
    31         {
    32             map[u][i]=map[i][u]=2;//标记为2使该边使用后不再被使用
    33             edge t={u,i};
    34             s.push(t);
    35             if(!vis[i])
    36             {
    37                 vis[i]=1;
    38                 depth++;
    39                 dfn[i]=low[i]=depth;
    40                 dfs(i);
    41                 low[u]=min(low[u],low[i]);
    42                 if(low[i]>=dfn[u])
    43                 {
    44                     while(1)//不断退栈,直到遇到边(u,v)
    45                     {
    46                         edge temp;
    47                         temp=s.top();
    48                         s.pop();
    49                         printf("%d-%d ",temp.x,temp.y);
    50                         if((temp.x==u&&temp.y==i)||(temp.x==i&&temp.y==u))
    51                         {
    52                             break;
    53                         }
    54                     }
    55                     printf("
    ");
    56                 }
    57             }
    58             else low[u]=min(low[u],dfn[i]);
    59         }
    60     }
    61 }
    62 int main()
    63 {
    64     int i,j,v,u;
    65     while(scanf("%d%d",&n,&m)!=EOF)
    66     {
    67         memset(map,0,sizeof(map));
    68         for(i=0;i<m;i++)
    69         {
    70             scanf("%d%d",&u,&v);
    71             map[u][v]=map[v][u]=1;
    72         }
    73         init();
    74         dfs(1);
    75     }
    76 }
    77 /*
    78 7 9
    79 1 2
    80 1 3
    81 1 6
    82 1 7
    83 2 3
    84 2 4
    85 2 5
    86 4 5
    87 6 7
    88 */
    View Code
  • 相关阅读:
    关系数据库&&NoSQL数据库
    NoSQL
    大数据时代的数据存储,非关系型数据库MongoDB
    判断是否为BST
    百度2017暑期实习生编程题
    memset()实现及细节
    在必须返回一个对象时,不要去尝试返回一个引用
    返回局部变量指针
    用引用返回值
    数组形参
  • 原文地址:https://www.cnblogs.com/sweat123/p/4551649.html
Copyright © 2020-2023  润新知