/*
首先给定一个有向图,这个图是原图经过floyd算法求出来的。原图的强连通分量到新图依然是强连通分量,而每个强连通分量都可以用一个环表示。
所以可以先将新图进行缩点,然后形成了一个有向无环图,对其进行floyd的反操作就可以了。
*/
// include file
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <ctime>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <bitset>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <list>
#include <functional>
using namespace std;
// typedef
typedef long long ll;
//
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
const double Pi = acos(-1.0);
const double eps = 1e-6;
const int IntMAX = 0x7fffffff;
const double DoubleMAX = 1e307;
#define TMIN(x,y) ( x<y?x:y )
int N;
bool G[210][210];
bool rG[210][210];
int Nx;
bool xG[210][210];
int ans;
bool visited[210];
int stk[210],top;
int dx[210];
int sz[210];
void dfs(int b)
{
visited[b] = true;
for(int i=1;i<=N;i++)
{
if( !visited[i] && G[b][i] )
{
dfs( i );
}
}
stk[top++] = b;
}
void rdfs(int b,int scc)
{
visited[b] =true;
dx[b] = scc;
sz[scc]++;
for(int i=1;i<=N;i++)
{
if( !visited[i] && rG[b][i] )
{
rdfs(i,scc);
}
}
}
void kosaraju()
{
memset(visited,0,sizeof(visited));
top = 0;
for(int i=1;i<=N;i++)
{
if( !visited[i] )
{
dfs( i );
}
}
//
memset(visited,0,sizeof(visited));
memset(sz,0,sizeof(sz));
int scc = 1;
for(int i=top-1;i>=0;i--)
{
if( !visited[stk[i]])
{
rdfs(stk[i] ,scc);
scc++;
}
}
for(int i=1;i<scc;i++) if( sz[i]>1) ans+=sz[i];
//
Nx = scc-1;
memset(xG,0,sizeof(xG));
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
{
if( G[i][j] && dx[i]!=dx[j] )
{
xG[dx[i]][dx[j]] = 1;
}
}
}
}
int main()
{
read;
write;
while(scanf("%d",&N)==1)
{
memset(rG,0,sizeof(rG));
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
{
scanf("%d",&G[i][j]);
if(i==j && G[i][j]) G[i][j] = 0;
if(G[i][j])
{
rG[j][i] = 1;
}
}
}
ans = 0;
kosaraju();
//
for(int k=1;k<=Nx;k++)
{
for(int i=1;i<=Nx;i++)
{
for(int j=1;j<=Nx;j++)
{
if( xG[i][j] && xG[i][k] && xG[k][j] )
{
xG[i][j] = 0;
}
}
}
}
for(int i=1;i<=Nx;i++) for(int j=1;j<=Nx;j++)
{
ans+=xG[i][j];
}
printf("%d\n",ans);
}
return 0;
}
转载于:https://www.cnblogs.com/ac2012/archive/2011/06/13/2079676.html