Tarjan 算法自我总结

 首先要说一下,强连通分量是指有向图里顶点间能互相到达的子图,并不一定要各点之间连在一起。 极大强连通图 是一个没有被其他连通图完全包含的图。

所以说Tarjan算法是来求强连通图的。

tarjan算法 代码如下:

void tar(int a)
{
 int i,b;
 dfn[a]=low[a]=++t; put(a);
 for(i=v[a].fir;i!=0;i=arcnum[i].next)
 {
 b=arcnum[i].go;
 if(dfn[b]==0)
 {
   tar(b);
   low[a]=min(low[a],low[b]);
    }
  else if(vis[b])
  low[a]=min(dfn[b],low[a]);
   }
   if(low[a]==dfn[a])
   {
    do
    {
       b=push();
       f[b]=k;
    }while(a!=b);
    k++;
   }
}

附上:POJ2186 代码:

#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=10000+100;
struct node{int data,fir;}v[maxn];
struct arcc{int go,next;}arcnum[70000];
int sum,top,stack[maxn];
void addarc(int a,int b)
{
	sum++;
	arcnum[sum].go=b;
	arcnum[sum].next=v[a].fir;
	v[a].fir=sum;
}
int low[maxn],dfn[maxn],t,vis[maxn],f[maxn],k=1,flag[maxn];
void put(int a)
{vis[a]=1; stack[++top]=a;}
int push()
{vis[stack[top]]=0; return stack[top--];}
void tar(int a)
{
	int i,b;
	dfn[a]=low[a]=++t; put(a);
	for(i=v[a].fir;i!=0;i=arcnum[i].next)
	{
	b=arcnum[i].go;
	if(dfn[b]==0)
	{
	  tar(b);
	  low[a]=min(low[a],low[b]);
    }
	 else if(vis[b])
	 low[a]=min(dfn[b],low[a]);
   }
   if(low[a]==dfn[a])
   {
   	do
   	{
   	   b=push();
   	   f[b]=k;
   	}while(a!=b);
   	k++;
   }
}
int outgdr[maxn];
int main()
{
	int n,m,i,j,a,b,jl;
	scanf("%d %d",&n,&m);
	for(i=1;i<=m;i++)
	{
	scanf("%d %d",&a,&b);
	addarc(a,b);
	}
	for(i=1;i<=n;i++)
	 if(!dfn[i])
	  tar(i);
	for(i=1;i<=n;i++)
	 for(j=v[i].fir;j!=0;j=arcnum[j].next)
	 {
	   a=f[i]; b=f[arcnum[j].go];
	   if(a!=b)
	   	outgdr[a]++;
     }
     
     a=0; b=0; 
    for(i=1;i<k;i++)
      if(outgdr[i]==0)
      	a++,jl=i;
    for(i=1;i<=n;i++)
      if(f[i]==jl)
        b++;
    if(a==1)
     printf("%d",b);
    else if(b==n)
    printf("%d",n);
    else
    printf("0");
	/*for(i=1;i<=n;i++)
     printf(" %d %d\n",i,f[i]);*/
   return 0;
}

值得注意的一点,int main()里面空间不足够多,如果开大一点儿的数组开在int main() 外才能开出来,否则数据大了,什么都输不出来,而且还会报错。

缩点: 是指把一个强连通图看成一个点,具体操作是,在tarjan里面,进行一部分修改,强连通分量里有写,就把它看成一个点,运用时候,加if语句判断即可。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值