#include <iostream>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>
#define MAXN 10005
using namespace std;
int dfn[MAXN];
int vis[MAXN];
int low[MAXN];
int belong[MAXN];//属于哪个联通分量
int stack[MAXN];
int dfs_num=0,top=0,cnt=0;
vector<int> G[MAXN];
void Tarjan(int x)
{
dfn[x] = ++dfs_num;
low[x] = dfs_num;
vis[x] = 1;
stack[++top] = x;
for(int i=0; i<G[x].size(); ++i)
{
int t = G[x][i];
if(!dfn[t])
{
Tarjan(t);
low[x] = min(low[x],low[t]);
}
else if(vis[t])
low[x] = min(low[x],dfn[t]);
}
if(dfn[x] == low[x])
{
cnt++;//联通分量的个数
int j;
do
{
j = stack[top--];
vis[j] = 0;
belong[j] = cnt;
}while(j != x);
}
}
int main(void)
{
// freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
int ncase;
cin >> ncase;
while(ncase--)
{
int n,m;
cin >> n >> m;
int in[n+1],out[n+1];
for(int i=0; i<=n; ++i) G[i].clear();
memset(dfn,0,sizeof(dfn));
memset(vis,0,sizeof(vis));
memset(low,0,sizeof(low));
memset(belong,0,sizeof(belong));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(stack,0,sizeof(stack));
dfs_num=0,top=0,cnt=0;
for(int i=0; i<m; ++i)
{
int u,v;
cin >> u >> v;
G[u].push_back(v);
}
for(int i=1; i<=n; ++i)
if(!dfn[i]) Tarjan(i);
if(cnt == 1)//特判
{
cout << '0'<<endl;
continue;
}
//缩点,将每个连通图看成一个点
for(int i=1; i<=n; ++i)
{
for(int j=0; j<G[i].size(); ++j)
{
if(belong[i] != belong[G[i][j]])
{
in[belong[G[i][j]]]++;
out[belong[i]]++;
}
}
}
int m1=0,m2=0;
//如果是强联通图,那么每个点至少有一个出度和入度
for(int i=1; i<=cnt; ++i)
{
if(!in[i]) m1++;
if(!out[i]) m2++;
}
cout << max(m1,m2)<<endl;
}
return 0;
}
Tarjan算法模板
最新推荐文章于 2020-09-02 11:13:53 发布