参考:http://blog.csdn.net/u010885899/article/details/50611895
开始看了几遍,真的很懵逼,看不懂题目。对着题解的代码看了好几遍,结合另一个题解才知道题目啥意思
另一个题解:http://blog.csdn.net/mengxiang000000/article/details/53670564
这里说的比较详细,我不扯淡了。
#include <bits/stdc++.h>
using namespace std;
#define CloseSync ios::sync_with_stdio(false),cin.tie(0)
const int MAXN = 1e5+10;
const int MAXM = 1e5+10;
struct Edge
{
int to,next;
};
Edge edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],Dfn[MAXN],Stack[MAXN],Belong[MAXN];
bool InStack[MAXN];
int flag[MAXN],f[MAXN];
int Index,top,scc;
int num[MAXN];
void init()
{
memset(head,-1,sizeof(head));
tot = 0;
}
void addedge(int u, int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void Tarjan(int u)
{
int v;
Low[u] = Dfn[u] = ++Index;
Stack[top++] = u;
InStack[u] = true;
for(int i = head[u]; i != -1; i = edge[i].next)
{
v = edge[i].to;
if(!Dfn[v])
{
Tarjan(v);
if(Low[v] < Low[u])
Low[u] = Low[v];
}
else if(InStack[v] && Dfn[v] < Low[u])
Low[u] = Dfn[v];
}
if(Low[u] == Dfn[u])
{
scc++;
do
{
v = Stack[--top];
InStack[v] = false;
Belong[v] = scc;
num[scc]++;
if(num[scc] != 1)
flag[scc] = 1;
else//这是强连通分量只有一个点的情况
flag[scc] = 0;
}while(v != u);
}
}
int getf(int s)
{
if(f[s] == -1)
return s;
return f[s]=getf(f[s]);
}
void calc(int n)
{
int s,e;
for(int i = 1; i <= n; ++i)
{
for(int j = head[i]; j != -1; j = edge[j].next)
{
s = Belong[i];
e = Belong[edge[j].to];
s = getf(s);
e = getf(e);
if(s != e)
{
f[s] = e;
num[e] += num[s];
flag[e] += flag[s];
}
}
}
}
void solve(int n)
{
memset(Dfn,0,sizeof(Dfn));
memset(InStack,0,sizeof(InStack));
memset(num,0,sizeof(num));
memset(f,-1,sizeof(f));
Index = scc = top = 0;
for(int i = 1; i <= n; ++i)
if(!Dfn[i])
Tarjan(i);
calc(n);
int res = 0;
for(int i = 1; i <= scc; ++i)
{
if(f[i] == -1)
{
if(flag[i] == 0)
res += (num[i]-1);
else
res += num[i];
}
}
cout << res << endl;
}
int main()
{
CloseSync;
int n,m,u,v;
cin >> n >> m;
init();
for(int i = 0; i < m; ++i)
{
cin >> u >> v;
addedge(u,v);
}
solve(n);
return 0;
}