codevs1506传话(kosaraju算法)

时间:2023-03-09 00:04:01
codevs1506传话(kosaraju算法)
- -   - -   - -   - -

一个()打成[]  看了一晚上.....

/*
求强连通分量 kosaraju算法
边表存图 正反构造两个图
跑两边 分别记下入栈顺序 和每个强连通分量的具体信息
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#define maxn 1010
#define maxx 10010
using namespace std;
int n,m,num,head1[maxn],head2[maxn],f[maxn],cnt;
int flag[maxn],ans[maxn][maxn];
stack<int>s;
struct node
{
int u,v,per;
}e1[maxx],e2[maxx];
void Input()//输入 构图 e1为正 e2为反
{
int i,x,y;
cin>>n>>m;
for(i=;i<=m;i++)
{
cin>>x>>y;
num++;
e1[num].u=x;
e1[num].v=y;
e1[num].per=head1[x];
head1[x]=num;
e2[num].u=y;
e2[num].v=x;
e2[num].per=head2[y];
head2[y]=num;
}
}
void Dfs1(int k)
{
f[k]=;
for(int p=head1[k];p;p=e1[p].per)
{
if(!f[e1[p].v])
Dfs1(e1[p].v);
}
s.push(k);//记录入栈顺序
}
void Dfs2(int k)
{
f[k]=;
ans[cnt][++ans[cnt][]]=k;//记下第cnt个强连通分量的每个点
for(int i=head2[k];i;i=e2[i].per)
if(f[e2[i].v]==)
Dfs2(e2[i].v);
if(ans[cnt][]>)flag[k]=;//如果第 cnt个强连通分量的大小>1 则x属于某个强连通分量
}
void Kosaraju()
{
memset(f,,sizeof(f));
for(int i=;i<=n;i++)//跑第一遍Dfs 每个点依次入栈
{
if(f[i]==)
Dfs1(i);
}
memset(f,,sizeof(f));
while(!s.empty())//跑第二遍Dfs 标记每个点是否属于一个强连通分量 并计算数量
{
int tmp=s.top();
s.pop();
if(f[tmp]==)
{
cnt++;//计数强连通分量
Dfs2(tmp);
}
}
}
void Printf()
{
for(int i=;i<=n;i++)
if(flag[i]==)cout<<"T"<<endl;
else cout<<"F"<<endl;
}
int main()
{
Input();
Kosaraju();
Printf();
return ;
}