强连通图的算法【Tarjan】+ 【HDU1269】 迷宫城堡
参考博客:https://blog.csdn.net/justlovetao/article/details/6673602
https://blog.csdn.net/qq_16234613/article/details/77431043 (代码含有注释)
问题:
for(int i=head[s]; i!=-1; i=edge[i].p)
{
int e=edge[i].e;
if(!dfn[e])
{
tanjar(e);
low[s]=min(low[s],low[e]);
}
else
{
if(instack[e]) ///为什么要进行判断
low[s]=min(low[s],dfn[e]);
}
}
将判断去掉和不去掉会得到不同强连通分量数量,如果不加 if(instack[e]) 那么 dfn[5]!=low[5],就会失去一个强连通分量 5.
例题:
///#include<bits/stdc++.h>
///#include<unordered_map>
///#include<unordered_set>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<bitset>
#include<set>
#include<stack>
#include<map>
#include<list>
#include<new>
#include<vector>
#define MT(a,b) memset(a,b,sizeof(a));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pai=acos(-1.0);
const double E=2.718281828459;
const ll mod=998424353;
const double INF=1e15;
const int maxn=1e5+5;
int n,m;
struct node
{
int e;
int p;
}edge[100005];
int sign,head[10005];
int time;
int dfn[10005],low[10005];
int Stack[10005],instack[10005],top;
int cnt;
void init()
{
cnt=0;
sign=0;
time=0;
top=0;
for(int i=1;i<=10000;i++)
{
head[i]=-1;
dfn[i]=low[i]=0;
instack[i]=0;
}
}
void add_edge(int s,int e)
{
edge[++sign]=node{e,head[s]};
head[s]=sign;
}
void tanjar(int s)
{
dfn[s]=low[s]=++time;
instack[s]=1;
Stack[++top]=s;
for(int i=head[s];i!=-1;i=edge[i].p)
{
int e=edge[i].e;
if(!dfn[e])
{
tanjar(e);
low[s]=min(low[s],low[e]);
}
else
{
if(instack[e])
low[s]=min(low[s],dfn[e]);
}
}
int t;
if(dfn[s]==low[s])
{
cnt++;
do
{
t=Stack[top--];
instack[t]=0;
}while(s!=t);
}
}
int main()
{
int s,e;
while(scanf("%d %d",&n,&m)!=EOF,n+m)
{
init();
for(int i=1;i<=m;i++)
{
scanf("%d %d",&s,&e);
add_edge(s,e);
}
tanjar(1);
for(int i=1;i<=n;i++)
{
if(!dfn[i])
tanjar(i);
}
printf(cnt==1?"Yes\n":"No\n");
}
return 0;
}