传送门:BZOJ1051
Tarjan算法求强联通分量,缩点,记录出度。
现学的Tarjan算法……++cnt写错了orz。
最近眼睛不舒服,做题好慢……
代码上的小细节见下。
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
struct Edge{
int u,v;
};
Edge edge[50005];
stack<int> Q;
int low[50005],dfn[50005];
vector<int> G[50005];
bool instack[50005];
int cnt;
int where[50005];
int scc;
int out[50005];
int have[50005];
int n,m;
int ans;
void Tarjan(int root)
{
low[root]=dfn[root]=++cnt;
instack[root]=true;
Q.push(root);
for(int i=0;i<G[root].size();i++){
int u=G[root][i];
if(low[u]==0){
Tarjan(u);
low[root]=min(low[root],low[u]);
}
else if(instack[u])
low[root]=min(low[root],dfn[u]);
}
if(low[root]==dfn[root]){
scc++;
int v;
do{
v=Q.top();
where[v]=scc;
instack[v]=false;
have[scc]++;
Q.pop();
}while(v!=root);
}
}
void Rebuild()
{
for(int i=1;i<=m;i++)
if(where[edge[i].u]!=where[edge[i].v])
out[where[edge[i].u]]++;
}
void First()
{
for(int i=1;i<=n;i++)
if(!dfn[i])
Tarjan(i);
Rebuild();
}
void Solve()
{
int jec=0;
for(int i=1;i<=scc;i++){
if(out[i]==0)
jec++,ans=i;
//printf("%d\n",out[i]);
}
printf("%d\n",jec==1?have[ans]:0);
}
void Close()
{
fclose(stdin);
fclose(stdout);
}
void Readdata()
{
freopen("loli.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&edge[i].u,&edge[i].v);
G[edge[i].u].push_back(edge[i].v);
}
}
int main()
{
Readdata();
First();
Solve();
Close();
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/le_ballon_rouge/article/details/47840703