强连通图
Tarjan算法
注意内存开大点,小了,只能通过80分。。。还不是太懂。。。待定!
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<stack>
#include<vector>
#include<string>
#include<string.h>
#define N 200010
using namespace std;
vector<int> G[N];
bool inStack[N];//表示是否在栈中
bool vis[N];//表示是否访问过
stack<int> S;
int DFN[N];
int LOW[N];
int time;//访问时序
int ans;
void Tarjan(int u)
{
DFN[u]=LOW[u]=++time;//访问时序从1开始
S.push(u);//入栈
inStack[u]=true;
vis[u]=true;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(vis[v]==false)
{
Tarjan(v);//如果没有访问过,就递归调用
LOW[u]=min(LOW[u],LOW[v]);
}
else if(inStack[v])
{//访问过了,那么若在栈中
LOW[u]=min(LOW[u],DFN[v]);
}
}
int m;
int cnt=0;//强连通子图中的顶点数目
if(DFN[u]==LOW[u])
{
do
{
m=S.top();
S.pop();
inStack[m]=false;
cnt++;
}while(m!=u);
if(cnt>1)
{
ans+=cnt*(cnt-1)/2;
}
}
}
int main()
{
while(!S.empty())
S.pop();
time=0;
ans=0;
memset(G,0,sizeof(G));
memset(DFN,0,sizeof(DFN));
memset(LOW,0,sizeof(LOW));
memset(vis,false,sizeof(vis));
memset(inStack,false,sizeof(inStack));
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
}
for(int i=1;i<=n;i++)
{
if(vis[i]==false)
{
Tarjan(i);
}
}
printf("%d\n",ans);
return 0;
}