Popular Cows--POJ 2186

1、题目类型:图论、强连通分量、Tarjan算法。

2、解题思路:(1)建立图的邻接表;(2)Trajan算法求解并记录强连通分量;(3)判断强连通分量的入度,当存在多个出度为0时,输出0;当只存在唯一出度为0的强连通分量,则输出其内部节点的个数。

3、注意事项:图用邻接表表示,矩阵表示MLE;注意M=0的情况。

4、实现方法:

  
    
#include < iostream >
#include
< stack >
using namespace std;

struct TNode
{
int data;
TNode
* next;
};

int n,m,index,cnt,bcnt;
int dfn[ 10010 ],low[ 10010 ];
int a[ 50010 ],b[ 50010 ],flag[ 10010 ];
TNode
* map[ 10010 ],data[ 500100 ];
bool vis[ 10010 ];
stack
< int > S;

void Tarjan( int v)
{
TNode
* tmp;
dfn[v]
= low[v] =++ cnt;
vis[v]
= true ;
S.push(v);
for (tmp = map[v];tmp != NULL;tmp = tmp -> next)
{
int i = tmp -> data;
if ( ! dfn[i])
{
Tarjan(i);
if (low[v] > low[i])
low[v]
= low[i];
}
else if (vis[i] && low[v] > dfn[i])
{
low[v]
= dfn[i];
}
}
if (low[v] == dfn[v])
{
bcnt
++ ;
int j;
do
{
j
= S.top();
S.pop();
// 用于标示点j在第bcnt个强连通分量里面
flag[j] = bcnt;
}
while (j != v);
}
}

int main()
{
int i,ans,pos;
TNode
* P, * pre;
cin
>> n >> m;
if (m == 0 )
{
cout
<< 0 << endl;
return 0 ;
}
// 建立邻接表
for (i = 1 ;i <= m;i ++ )
{
cin
>> a[i] >> b[i];
P
=& data[index ++ ];
P
-> data = b[i];
if (map[a[i]] == NULL)
{
map[a[i]]
= P;
}
else
{
pre
= map[a[i]] -> next;
P
-> next = pre;
map[a[i]]
-> next = P;
}
}
for (i = 1 ;i <= n;i ++ )
{
if ( ! dfn[i])
Tarjan(i);
}

memset(vis,
0 , sizeof (vis));
for (i = 1 ;i <= m;i ++ )
{
if (flag[a[i]] != flag[b[i]])
vis[flag[a[i]]]
= 1 ;
}
cnt
= 0 ;
for (i = 1 ;i <= bcnt;i ++ )
{
if ( ! vis[i])
{
cnt
++ ;
pos
= i;
}
}
if (cnt > 1 )
{
cout
<< 0 << endl;
}
else
{
ans
= 0 ;
for (i = 1 ;i <= n;i ++ )
if (flag[i] == pos)
ans
++ ;
cout
<< ans << endl;
}
return 0 ;
}

 

 

 

你可能感兴趣的:(poj)