• tarjan求强连通分量 + 缩点 + 求割点割边


    强连通分量:

           引用度娘:“有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量(strongly connected components)。”

           就是在一幅图里,任意两点可以相互到达,这一幅图就是一个强连通分量。

           

           这幅图中强连通分量有三个,为:1-2-3、4、5 。

    强连通分量的应用:

           1、缩点。 

           2、求割点和割边的数量。

    代码:

    tarjan 模版 + 缩点

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define MOD 998244353 
     4 #define INF 0x3f3f3f3f
     5 #define mem(a,x) memset(a,x,sizeof(a))  
     6 using namespace std;
     7 int dfn[50005];
     8 int low[50005];
     9 int vis[50005];
    10 int stacks[50005];
    11 int color[50005];
    12 int cnt[50005];
    13 int deep,sum,top;
    14 int n,m;
    15 vector<int>g[50005];
    16 void tarjan(int u)
    17 {
    18    dfn[u]=++deep;
    19    low[u]=deep;
    20    vis[u]=1;
    21    stacks[++top]=u;
    22    for(int i=0;i<g[u].size();i++){
    23        int v=g[u][i];
    24        if(!dfn[v])
    25        {
    26           tarjan(v);
    27           low[u]=min(low[u],low[v]);
    28        }else{
    29            if(vis[v]){
    30               low[u]=min(low[v],low[u]);
    31            }
    32        }
    33    }
    34    if(dfn[u]==low[u])
    35    {
    36       color[u]=++sum;
    37       vis[u]=0;
    38       while(stacks[top]!=u)
    39       {
    40           color[stacks[top]]=sum;
    41           vis[stacks[top--]]=0;
    42       }
    43       top--;
    44    }
    45 }
    46 int main()
    47 {
    48     deep=0;
    49     top=0;
    50     sum=0;
    51     mem(dfn,0);
    52     mem(vis,0);
    53     mem(cnt,0);
    54     scanf("%d %d",&n,&m);
    55     while(m--){
    56        int from,to;
    57        scanf("%d %d",&from,&to);
    58        g[from].push_back(to);
    59     }
    60     for(int i=1;i<=n;i++){
    61         if(!dfn[i]){
    62            tarjan(i);
    63         }
    64     }
    65     int num=0;
    66     for(int i=1;i<=n;i++){
    67         cnt[color[i]]++;
    68     }
    69     for(int i=1;i<=sum;i++){
    70       if(cnt[i]>1)num++;
    71     }
    72     cout<<num;
    73     return 0;
    74 }

    tarjan 求割点

    在原来的tarjan 基础上 加一个特判:如果一个点的为根节点且这个点有两个及以上的儿子,这个点就是割点。

    代码:

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define MOD 998244353 
     4 #define INF 0x3f3f3f3f
     5 #define mem(a,x) memset(a,x,sizeof(a))  
     6 using namespace std;
     7 int n,m;
     8 int deep=0,root;
     9 vector<int>g[200015];
    10 int dfn[100015];
    11 int low[100015];
    12 int stack[100015];
    13 int vis[100015];
    14 int iscut[100015];
    15 int tarjan(int u,int fa)
    16 {
    17     int child=0,lowu;
    18     lowu=dfn[u]=++deep;
    19     int sz=g[u].size();
    20     for(int i=0;i<sz;i++)
    21     {
    22         int v=g[u][i];
    23         if(!dfn[v])
    24         {
    25             int v=g[u][i];
    26             int lowv=tarjan(v,u);
    27             lowu=min(lowu,lowv);
    28             if(lowv>dfn[u])
    29             {
    30                 iscut[u]=1;
    31             }
    32         }else{
    33             if(v!=fa&&dfn[v]<dfn[u])
    34             {
    35                 lowu=min(lowu,dfn[v]);
    36             }
    37         }
    38     }
    39     if(fa<0&&child==1)
    40     {
    41         iscut[u]=0;
    42     }
    43     low[u]=lowu;
    44     return lowu;
    45 }
    46 int main()
    47 {
    48      scanf("%d %d",&n,&m);
    49      for(int i=1;i<=m;i++){
    50          int from,to;
    51          scanf("%d %d",&from,&to);
    52          g[from].push_back(to);
    53          g[to].push_back(from);
    54      }
    55      for(int i=1;i<=n;i++){
    56          if(!vis[i]){
    57            root=i;
    58            tarjan(i,-1);
    59          }
    60      }
    61      int ans=0;
    62      for(int i=1;i<=n;i++){
    63          if(iscut[i]){
    64              ans++;
    65          }
    66      }
    67      printf("%d
    ",ans);
    68      for(int i=1;i<=n;i++){
    69          if(iscut[i]){
    70              printf("%d ",i);
    71          }
    72      }
    73      return 0;
    74 }

    求割边

     1 #include<cstdio> 
     2 #include<vector>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #define hi printf("hi!");
     7 using namespace std;
     8 
     9 vector<pair<int,int> >bridge;
    10 vector<int> g[10010];
    11 int dfn[10010],low[10010];
    12 int deep,root,n,m,ans;
    13 
    14 int tarjan(int u,int fa)
    15 {
    16     int lowu;
    17     lowu=dfn[u]=++deep;
    18     int sz=g[u].size();
    19     for(int i=0;i<sz;i++)
    20     {
    21         int v=g[u][i];
    22         if(!dfn[v])
    23         {
    24             int lowv=tarjan(v,u);
    25             lowu=min(lowu,lowv);
    26             if(lowv>dfn[u])
    27             {
    28                 int from,to;
    29                 from=u;
    30                 to=v;
    31                 if(from>to)
    32                 {
    33                     swap(from,to);
    34                 }
    35                 bridge.push_back(make_pair(from,to));
    36             }
    37         }
    38         else
    39         {
    40             if(v!=fa&&dfn[v]<dfn[u])
    41             {
    42                 lowu=min(lowu,dfn[v]);
    43             }
    44         } 
    45     }
    46     low[u]=lowu;
    47     return lowu;
    48 } 
    49 
    50 int main()
    51 {
    52     scanf("%d%d",&n,&m);
    53     for(int i=1;i<=m;i++)
    54     {
    55         int from,to;
    56         scanf("%d%d",&from,&to);
    57         g[from].push_back(to);
    58         g[to].push_back(from);
    59     }
    60     for(int i=1;i<=n;i++)
    61     {
    62         if(!dfn[i])
    63         {
    64             root=i;
    65             tarjan(i,-1);
    66         }
    67     }
    68     for(int i=0;i<bridge.size();i++)
    69     {
    70         printf("%d %d
    ",bridge[i].first,bridge[i].second);
    71     }
    72 }
    越自律,越自由
  • 相关阅读:
    GoogleTest初探(2)
    GoogleTest初探(1)
    GoogleMock初探(0)
    GoogleTest初探(0)
    [leetcode] 二叉树的前序,中序,后续,层次遍历
    关于phpmyadmin报403错误forbidden
    如何使用Fiddler抓取Android手机数据请求
    安全性测试之安装包测试
    二代身份证号码编码规则
    Excel导入功能测试用例整理
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/13562142.html
Copyright © 2020-2023  润新知