题意:给出一个有向图,求一共有多少个点,满足这样的条件:所有其它的点都可以到达这个点。
分析:强连通分支+缩点,然后统计每个强连通分支的出度,如果只有一个为0,则输出其内部点的个数,如果有多个为0,说明没有答案。
View Code
#include
<
iostream
>
#include < cstdlib >
#include < cstring >
#include < cstdio >
using namespace std;
#define maxn 10005
#define maxm 50005
struct Edge
{
int v, next;
} edge[maxm], opedge[maxm];
int n, m, head[maxn], ophead[maxn], ncount, nowtime, pos[maxn * 2 ], sig[maxn], signnum, in [maxn];
int pointnum[maxn];
bool flag[maxn];
void addedge( int a, int b)
{
edge[ncount].v = b;
edge[ncount].next = head[a];
head[a] = ncount;
opedge[ncount].v = a;
opedge[ncount].next = ophead[b];
ophead[b] = ncount;
ncount ++ ;
}
void input()
{
scanf( " %d%d " , & n, & m);
for ( int i = 0 ; i < m; i ++ )
{
int a, b;
scanf( " %d%d " , & a, & b);
a -- ;
b -- ;
addedge(a, b);
}
}
void dfs( int a)
{
flag[a] = true ;
pos[nowtime] = a;
nowtime ++ ;
for ( int i = head[a]; i != - 1 ; i = edge[i].next)
if ( ! flag[edge[i].v])
dfs(edge[i].v);
pos[nowtime] = a;
nowtime ++ ;
}
void rdfs( int a)
{
flag[a] = true ;
sig[a] = signnum;
pointnum[sig[a]] ++ ;
for ( int i = ophead[a]; i != - 1 ; i = opedge[i].next)
if ( ! flag[opedge[i].v])
rdfs(opedge[i].v);
}
int main()
{
// freopen("t.txt", "r", stdin);
ncount = 0 ;
memset(head, - 1 , sizeof (head));
memset(ophead, - 1 , sizeof (ophead));
memset(flag, 0 , sizeof (flag));
input();
nowtime = 1 ;
for ( int i = 0 ; i < n; i ++ )
if ( ! flag[i])
dfs(i);
memset(flag, 0 , sizeof (flag));
memset(pointnum, 0 , sizeof (pointnum));
signnum = 0 ;
for ( int i = 2 * n; i > 0 ; i -- )
if ( ! flag[pos[i]])
{
rdfs(pos[i]);
signnum ++ ;
}
memset( in , 0 , sizeof ( in ));
ncount = 0 ;
for ( int i = 0 ; i < n; i ++ )
for ( int j = head[i]; j != - 1 ; j = edge[j].next)
if (sig[i] != sig[edge[j].v])
in [sig[i]] ++ ;
int ans = - 1 ;
bool ok = true ;
for ( int i = 0 ; i < signnum; i ++ )
if ( in [i] == 0 )
{
if (ans != - 1 )
{
ok = false ;
break ;
}
ans = i;
}
if (ok)
printf( " %d\n " , pointnum[ans]);
else
printf( " 0\n " );
return 0 ;
}
#include < cstdlib >
#include < cstring >
#include < cstdio >
using namespace std;
#define maxn 10005
#define maxm 50005
struct Edge
{
int v, next;
} edge[maxm], opedge[maxm];
int n, m, head[maxn], ophead[maxn], ncount, nowtime, pos[maxn * 2 ], sig[maxn], signnum, in [maxn];
int pointnum[maxn];
bool flag[maxn];
void addedge( int a, int b)
{
edge[ncount].v = b;
edge[ncount].next = head[a];
head[a] = ncount;
opedge[ncount].v = a;
opedge[ncount].next = ophead[b];
ophead[b] = ncount;
ncount ++ ;
}
void input()
{
scanf( " %d%d " , & n, & m);
for ( int i = 0 ; i < m; i ++ )
{
int a, b;
scanf( " %d%d " , & a, & b);
a -- ;
b -- ;
addedge(a, b);
}
}
void dfs( int a)
{
flag[a] = true ;
pos[nowtime] = a;
nowtime ++ ;
for ( int i = head[a]; i != - 1 ; i = edge[i].next)
if ( ! flag[edge[i].v])
dfs(edge[i].v);
pos[nowtime] = a;
nowtime ++ ;
}
void rdfs( int a)
{
flag[a] = true ;
sig[a] = signnum;
pointnum[sig[a]] ++ ;
for ( int i = ophead[a]; i != - 1 ; i = opedge[i].next)
if ( ! flag[opedge[i].v])
rdfs(opedge[i].v);
}
int main()
{
// freopen("t.txt", "r", stdin);
ncount = 0 ;
memset(head, - 1 , sizeof (head));
memset(ophead, - 1 , sizeof (ophead));
memset(flag, 0 , sizeof (flag));
input();
nowtime = 1 ;
for ( int i = 0 ; i < n; i ++ )
if ( ! flag[i])
dfs(i);
memset(flag, 0 , sizeof (flag));
memset(pointnum, 0 , sizeof (pointnum));
signnum = 0 ;
for ( int i = 2 * n; i > 0 ; i -- )
if ( ! flag[pos[i]])
{
rdfs(pos[i]);
signnum ++ ;
}
memset( in , 0 , sizeof ( in ));
ncount = 0 ;
for ( int i = 0 ; i < n; i ++ )
for ( int j = head[i]; j != - 1 ; j = edge[j].next)
if (sig[i] != sig[edge[j].v])
in [sig[i]] ++ ;
int ans = - 1 ;
bool ok = true ;
for ( int i = 0 ; i < signnum; i ++ )
if ( in [i] == 0 )
{
if (ans != - 1 )
{
ok = false ;
break ;
}
ans = i;
}
if (ok)
printf( " %d\n " , pointnum[ans]);
else
printf( " 0\n " );
return 0 ;
}