poj2186:题目链接
题目大意:有n头奶牛,m个关系,A B表示A奶牛认为B是备受关注的,这个关系具有继承性,比如:A B 和 B C那么A奶牛也会认为C是备受关注的,问有多少头奶牛是受到除自己以外所以人关注的
首先进行强连通,那么每个连通块中的点都是受到该连通块中其它点的关注的,进行缩点,原图变成一颗树,如果有且只有一个缩点以后的点的出度为0,那么这个点就是受到所有人关注的。记录下该点代表原图中的几个点,输出
不用考虑是否所有点在一个图中,因为如果不在一个图中,不会满足“有且只有一个缩点以后的点的出度为0”
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std ;
struct node
{
int u , v ;
int next ;
} edge[51000] , tree[51000] ;
int head[11000] , h_tree[11000] , cnt ;
int dnf[11000] , low[11000] , time ;
int vis[11000] , in[11000] , belong[11000] , num ;
int sum[11000] ;
stack <int> sta ;
void init()
{
memset(head,-1,sizeof(head)) ;
cnt = time = num = 0 ;
memset(dnf,0,sizeof(dnf)) ;
memset(low,0,sizeof(low)) ;
memset(vis,0,sizeof(vis)) ;
memset(in,0,sizeof(in)) ;
memset(belong,0,sizeof(belong)) ;
memset(sum,0,sizeof(sum)) ;
while( !sta.empty() ) sta.pop() ;
}
void add(int u,int v)
{
edge[cnt].u = u ;
edge[cnt].v = v ;
edge[cnt].next = head[u] ;
head[u] = cnt++ ;
}
void add_tree(int u,int v)
{
tree[cnt].u = u ;
tree[cnt].v = v ;
tree[cnt].next = h_tree[u] ;
h_tree[u] = cnt++ ;
}
void tarjan(int u)
{
dnf[u] = low[u] = ++time ;
sta.push(u) ;
vis[u] = 1 ;
int i , v , j ;
for(i = head[u] ; i != -1 ; i = edge[i].next)
{
v = edge[i].v ;
if( !dnf[v] )
{
tarjan(v) ;
low[u] = min(low[u],low[v]) ;
}
else if( vis[v] )
{
low[u] = min(low[u],dnf[v]) ;
}
}
if( low[u] == dnf[u] )
{
++num ;
while( 1 )
{
j = sta.top() ;
sta.pop() ;
vis[j] = 0 ;
belong[j] = num ;
sum[num]++ ;
if( j == u ) break ;
}
}
}
int main()
{
int n , m , ans ;
int u , v , i , j ;
while( scanf("%d %d", &n, &m) != EOF )
{
init() ;
ans = 0 ;
while( m-- )
{
scanf("%d %d", &u, &v) ;
add(u,v) ;
}
for(i = 1 ; i <= n ; i++)
if( !dnf[i] ) tarjan(i) ;
memset(in,0,sizeof(in)) ;
for(i = 1 ; i <= n ; i++)
{
for(j = head[i] ; j != -1 ; j = edge[j].next)
{
u = belong[ edge[j].u ] ;
v = belong[ edge[j].v ] ;
if( u != v )
in[u]++ ;
}
}
for(i = 1 ; i <= num ; i++)
if( in[i] == 0 )
{
ans += sum[i] ;
sum[0]++ ;
}
if( sum[0] == 1 )
printf("%d\n", ans) ;
else
printf("0\n") ;
}
return 0 ;
}