题目大意:给定m条有向边,求出有多少点,以任意一个点为起始点时都能到达。
解题思路:Tarjan.
自己做了一个特别渣的Tarjan类,Tarjan题直接套模板就好了。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
#define MAXN 10100
#define MAXM 50100
struct PPP
{
int point,next,val;
};
class Link
{
public:
int now[MAXN];
struct PPP link[MAXM];
void insert(int a,int b)
{
tail++;
link[tail].point = b;
link[tail].next = now[a];
now[a] = tail;
}
void insert(int a,int b,int c)
{
tail++;
link[tail].point = b;
link[tail].val = c;
link[tail].next = now[a];
now[a] = tail;
}
void clear()
{
memset(now,0,sizeof(now));
memset(link,0,sizeof(link));
tail = 0;
}
private:
int tail;
};
int d[MAXN];
int n,m;
class Tarjan
{
private:
int low[MAXN],dfn[MAXN];
int ins[MAXN],stack[MAXN],belong[MAXN];
int deep,top;
void dfs(int u)
{
int v;
deep++;
low[u] = deep;
dfn[u] = deep;
stack[++top] = u;
ins[u] = 1;
for (int i = list1.now[u] ; i != 0 ; i = list1.link[i].next)
{
v = list1.link[i].point;
if (!dfn[v]) {
dfs(v);
low[u] = min(low[u],low[v]);//low[u]<low[v]?low[u]:low[v];
}
else {
if (ins[v]) {
low[u] = min(low[u],dfn[v]);//low[u]<dfn[v]?low[u]:dfn[v];
}
}
}
if (low[u] == dfn[u]) {
length++;
do
{
v = stack[top--];
belong[v] = length;
ins[v] = 0;
}while (u != v);
}
}
void rebuild()
{
//新表对于权值的含义
for (int i = 1 ; i <= n ; i ++) weight[belong[i]] ++;
for (int u = 1 ; u <= n ; u ++)
{
for (int e = list1.now[u] ; e != 0 ; e = list1.link[e].next)
{
int v = list1.link[e].point;
if (belong[u] != belong[v])
{
list2.insert(belong[u],belong[v],weight[belong[u]]);
}
}
}
}
public:
int weight[MAXN];
int length;
Link list1,list2;
void clear()
{
list1.clear();
list2.clear();
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(ins,0,sizeof(ins));
memset(weight,0,sizeof(weight));
memset(stack,0,sizeof(stack));
memset(belong,0,sizeof(belong));
deep = top = length = 0;
}
void work()
{
for (int i = 1 ; i <= n ; i ++)
if (!dfn[i]) {
dfs(i);
}
rebuild();
}
void insert(int a,int b) {list1.insert(a,b);}
void insert(int a,int b,int c) {list1.insert(a,b,c);}
}tarjan;
int main()
{
int t;
int x,y;
while (scanf("%d%d",&n,&m) != EOF)
{
memset(d,0,sizeof(d));
tarjan.clear();
for (int i = 1 ; i <= m ; i ++)
{
scanf("%d%d",&x,&y);
tarjan.insert(x,y);
}
tarjan.work();
int ans = 0;
int boo = 0;
int temp;
for (int i = 1 ; i <= tarjan.length ; i ++)
{
temp = 0;
for (int j = tarjan.list2.now[i];j != 0 ; j = tarjan.list2.link[j].next)
temp ++;
if (temp == 0) {
ans += tarjan.weight[i];
boo++;
}
}
if (boo == 1) printf("%d\n",ans);
else printf("0\n",ans);
}
return 0;
}