Luogu p2683 神奇ac代码+Tarjan模板

题目链接

Tarjan算法

这是一个求一个图中的强连通分量的算法。强连通分量是指这一个子图中所有节点都能互相到达。当然,Tarjan的效率很高,时间复杂度为O(n+m)。

这里我们要用到两个关键的数组,一个是dfn,简称豆腐脑,是记录每一个节点在dfs中是第几个被搜到的(时间戳),还有一个就是low,代表了每一个节点的根,就是它的强连通分量的起始点。

当一个点没有被搜到过,就继续往下搜,并且更新走到自己身上的点的dfn。当一个点第二次被找到时,证明它已经在一个强连通分量里了,所以就要认找到你的人为根(更新low)

当一个点一次dfs过后还没被搜到,就以这个点继续搜。

具体代码如下

#include
using namespace std;
inline int read(){
	int s=0,f=1;char c=getchar();
	for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
	for(;isdigit(c);c=getchar())s=(s<<3)+(s<<1)+(c^48);
	return s*f;
}
inline void write(int x){
	if(x<0){putchar('-');x=-x;}
	if(x>9) write(x/10);
	putchar(x%10+'0');
}
//读入输出优化 
int dfn[10001],low[10001],n,m,ans=0;  //dfn:每个点第几个被搜到的(时间戳)
//low: 作为每个点在这颗树中的,最小的子树的根,每次保证最小,like它的父亲结点的时间戳这种感觉。如果它自己的LOW[]最小,那这个点就应该重新分配,变成这个强连通分量子树的根节点。 
int visit[10001],tot;  //visit:有没有被搜到过的标记。tot:现在是第几个单位时间 
vector<int>v[10001];//邻接表 
stack<int>s;//栈 
void tarjan(int x)  
{  
     dfn[x]=low[x]=++tot;  //将找到的这个点的dfn和low都改成 当前时间戳。 
     s.push(x); //入栈 
     visit[x]=1;//标记 
    for(int i=0;i<v[x].size();i++)  
     {  
         if(!dfn[v[x][i]]) { //当前点没有被找到过(没有定义过dfn等同于没有被找到过) 
             tarjan(v[x][i]); //继续往下搜 
             low[x]=min(low[x],low[v[x][i]]);  //更新low 
        }  
        else if(visit[v[x][i]]){   //当前点被找到过了 
             low[x]=min(low[x],dfn[v[x][i]]); //用搜到的点的dfn去更新当前点的low 
        }  
     }  
     if(low[x]==dfn[x])  //如果当前点就是自己的根 
    {  
    	int t=0;
        while(s.top()!=x){
        	t++;
        	visit[s.top()]=0;s.pop();
        }//出栈 
        s.pop();visit[x]=0;
        if(t)ans++;//强连通分量个数加一 
     }  
     return;  
}  
int main()  
{  
     n=read();m=read(); 
     for(int i=1;i<=m;i++)  
     {  
        int x=read(),y=read();
        v[x].push_back(y);//建邻接表 
     }  
    for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);//如果当前点没被找到过就以当前点为中心去tarjan 
    printf("%d\n",ans);
    return 0;  
}  


下面是一段玄学的TarjanAC代码

#include
#define ______________________________ int
#define _____________________________ 10001
using namespace std;
inline ______________________________ read(){
       ______________________________ ___=0,_=1;char _______________________=getchar();
       while(!isdigit(_______________________)){if(_______________________=='-')_=-1;_______________________=getchar();}
       while(isdigit(_______________________)){___=___*10+_______________________-'0';_______________________=getchar();}
       return ___*_;
}
inline void write(______________________________ __________________){
       if(__________________<0){putchar('-');__________________=-__________________;}
       if(__________________>9)write(__________________/10);
       putchar(__________________%10+'0');
}
______________________________ ____________[_____________________________],_____________[_____________________________],n,m,________________=0;  
______________________________ ______________[_____________________________],_________________________,________________________;  
vector<______________________________>_____[_____________________________];
stack<______________________________>___;
void _______________(______________________________ __________________)  
{  
     ____________[__________________]=_____________[__________________]=++________________________;  
     ___.push(__________________); 
     ______________[__________________]=1;
    for(______________________________ i=0;i<_____[__________________].size();i++)  
     {  
         if(!____________[_____[__________________][i]]) { 
             _______________(_____[__________________][i]); 
             _____________[__________________]=min(_____________[__________________],_____________[_____[__________________][i]]);  
        }  
        else if(______________[_____[__________________][i]]){   
             _____________[__________________]=min(_____________[__________________],____________[_____[__________________][i]]); 
        }  
     }  
     if(_____________[__________________]==____________[__________________])  
    {  
    	______________________________ t=0;
        while(___.top()!=__________________){
        	t++;
        	______________[___.top()]=0;___.pop();
        }
        ___.pop();______________[__________________]=0;
        if(t)________________++;
     }  
     return;  
}  
______________________________ main()  
{  
     n=read();m=read(); 
     for(______________________________ i=1;i<=m;i++)  
     {  
        ______________________________ __________________=read(),y=read();
        _____[__________________].push_back(y); 
     }  
    for(______________________________ i=1;i<=n;i++)if(!____________[i])_______________(i);
    printf("%d\n",________________);
    return 0;  
}  

你可能感兴趣的:(Tarjan)