B-Network (tarjan finds the cut point and bridge board)

https://www.luogu.com.cn/problem/UVA315


board:

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=200;
typedef long long LL;
vector<LL>g[maxn];
LL fa[maxn],dfn[maxn],low[maxn],times=0;
bool ge[maxn];
void tarjan2(LL x)
{
    dfn[x]=low[x]=++times;
    LL child=0;
    for(LL i=0;i<g[x].size();i++)
    {
        LL to=g[x][i];
        if(!dfn[to])
        {
            child++;fa[to]=x;
            tarjan2(to);
            if(-1==fa[x]&&child>=2) ge[x]=true;
            if(-1!=fa[x]&&low[to]>=dfn[x]) ge[x]=true;
            if(low[to]>dfn[x]){
               ///cout<<x<<"->"<<to<<" is bridge"<<endl;
            }
            low[x]=min(low[x],low[to]);
        }
        else if(to!=fa[x]) low[x]=min(low[x],dfn[to]);
    }
}
int main(void)
{
    for(LL i=1;i<=n;i++) if(!dfn[i]) tarjan2(i);
}

Understanding of the algorithm:

Note 1: The second update of dfn is not empty nodes, pay attention to min(low[x],dfn[to]);

https://blog.csdn.net/Kamisama123/article/details/75007415 (Explanation of this place)

Consider this picture:
if we update low[u] with low[v], an existing traversal sequence will lead to such a situation.
The dfn of node 3 is 3, low is 1, the dfn of node 5 is 5, low is 1, the dfn of node 4 is 4, and low is 1.
This situation results in 3 not being judged as a cut point.


Note 2: Judging the relationship between the son and the father is in the search tree. So when x is root and there are two sons, there is only one situation.

Note 3: x is the cut point. cas1: non-root point && has a son&&low[x’s son]>=dfn[x];

case2: root point && has >= 2 sons

xy is the bridge: low[y]>dfn[x];

Review reference video: https://www.bilibili.com/video/BV1GE411G7Kq


About this question: It is a board question of cutting points. The input is more cancerous.

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=200;
typedef long long LL;
vector<LL>g[maxn];
LL fa[maxn],dfn[maxn],low[maxn],times=0;
bool ge[maxn];
void tarjan2(LL x)
{
    dfn[x]=low[x]=++times;
    LL child=0;
    for(LL i=0;i<g[x].size();i++)
    {
        LL to=g[x][i];
        if(!dfn[to])
        {
            child++;fa[to]=x;
            tarjan2(to);
            if(-1==fa[x]&&child>=2) ge[x]=true;
            if(-1!=fa[x]&&low[to]>=dfn[x]) ge[x]=true;
            if(low[to]>dfn[x]){
               ///cout<<x<<"->"<<to<<" is bridge"<<endl;
            }
            low[x]=min(low[x],low[to]);
        }
        else if(to!=fa[x]) low[x]=min(low[x],dfn[to]);
    }
}
int main(void)
{
  ///cin.tie(0);std::ios::sync_with_stdio(false);
  LL n;
  while(cin>>n&&n)
  {
    memset(fa,-1,sizeof(fa));memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));memset(ge,0,sizeof(ge));
    times=0;
    for(LL i=0;i<=n+10;i++) g[i].clear();
    LL sz;
    while(cin>>sz&&sz)
    {
        while(1)
        {
            char ch=getchar();if(ch=='\n') break;
            LL v;cin>>v;
            g[sz].push_back(v);g[v].push_back(sz);
        }
    }
    LL sum=0;
    for(LL i=1;i<=n;i++) if(!dfn[i]) tarjan2(i);
    for(LL i=1;i<=n;i++) if(ge[i]) sum++;
    cout<<sum<<endl;
  }
  return 0;
}

 

Guess you like

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/108888061