您的位置:首页 > 其它

强联通分量 缩点 tarjan算法

2014-03-30 13:07 357 查看
/*做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间最早的节点的开始时间。初始时dfn[i]=low[i]

在DFS过程中会形成一搜索树。在搜索树上越先遍历到的节点,显然dfn的值就越小。

DFS过程中,碰到哪个节点,就将哪个节点入栈。栈中节点只有在其所属的强连通分量已经全部求出时,才会出栈。

如果发现某节点u有边连到搜索树中栈里的节点v,则更新u的low 值为dfn[v](更新为low[v]也可以)。
如果一个节点u已经DFS访问结束,而且此时其low值等于dfn值,则说明u可达的所有节点,都不能到达任何在u之前被DFS访问的节点 ---- 那么该节点u就是一个强连通分量在DFS搜索树中的根。

此时将栈中所有节点弹出,包括u,就找到了一个强连通分量*/

/*本体题意:
*有N(N<=10000)头牛,每头牛都想成为most poluler的牛;
*给出M(M<=50000)个关系,如(1,2)代表1欢迎2,关系可以传递,但是不可以相互,即1欢迎2不代表2欢迎1;
*但是如果2也欢迎3那么1也欢迎3;
*给出N,M和M个欢迎关系,求被所有牛都欢迎的牛的数量;
*求出强联通分量后,所以解题的方法就应该是在缩点之后的图G中求出所有出度为零的点的个数,如果个数大于1,
说明至少存在两个分量之间的牛不会相互YM,明显和题目要求不符合,输出0,如果等于1则说明只有一个强连通分
量里面的牛被其他全部的牛YM,那么答案就是这个分量中点的个数
*/
#include <cstdio>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#define N 50010
using namespace std;
int dfs
,instack
,low
,out
,belong
;
int stack
;
int deep,top,cnt,n,m;
vector<int> map
;
int min(int a,int b)
{
return a>b?b:a;
}
void tarjan(int k)
{
int i,j;
dfs[k]=low[k]=++deep;
stack[++top]=k;
instack[k]=1;
for(i=0; i<map[k].size(); i++)
{
j=map[k][i];
if(dfs[j]==0)
{
tarjan(j);
low[k]=min(low[k],low[j]);
}
else        if(instack[j])
{
low[k]=min(low[k],dfs[j]);
}
}
if(low[k]==dfs[k])
{
cnt++;
do
{
j=stack[top--];
belong[j]=cnt;
instack[j]=0;
}
while(j!=k);
}
}
int main()
{
int i,j,a,b,ans,num,pos;

while(scanf("%d%d",&n,&m)!=EOF)
{
memset(dfs,0,sizeof(dfs));
memset(instack,0,sizeof(instack));
memset(low,0,sizeof(low));
memset(out,0,sizeof(out));
memset(belong,0,sizeof(belong));
memset(stack,0,sizeof(stack));
memset(map,0,sizeof(map));
deep=top=cnt=0;

for(i=1; i<=m; i++)
{
scanf("%d%d",&a,&b);
map[a].push_back(b);
}
for(i=1; i<=n; i++)
if(dfs[i]==0)
tarjan(i);
if(cnt==1)
{
printf("%d\n",n);
continue;
}
for(i=1; i<=n; i++)
for(j=0; j<map[i].size(); j++)
if(belong[i]!=belong[map[i][j]])
{
out[belong[i]]++;
}
ans=pos=num=0;
for(i=1; i<=cnt; i++)
if(!out[i])
{
num++;
pos=i;
}
if(num==1)
{
for(j=1; j<=n; j++)
if(belong[j]==pos)
{
ans++;
}
printf("%d\n",ans);
}
else printf("0\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息