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;
}