[HAOI2006]受欢迎的牛 G-强连通分量
作者:互联网
题目
题目
tarjan算法每次打都要翻书,于是就学了一个叫Korasaju算法的东西
程序
给定有向图,缩点,判断是不是只有一个点出度为0,是,输出,否则输出0。
#include <iostream>
#include <cstring>
using namespace std;
const int N=2E5+10,M=2E5+10;
int scc[N],sc;
int to1[M],nxt1[M],head1[M],cnt1;
int to2[M],nxt2[M],head2[M],cnt2;
int to[M],nxt[M],head[M],cnt;
bool v[N],vis[N],f;
int t[N];
int s[N],tot;
int n,m,ans;
void add(int u,int v) {
to[++cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
}
void add1(int u,int v) {
to1[++cnt1]=v;
nxt1[cnt1]=head1[u];
head1[u]=cnt1;
}
void add2(int u,int v) {
to2[++cnt2]=v;
nxt2[cnt2]=head2[u];
head2[u]=cnt2;
}
void dfs1(int p) {
v[p]=true;
for(int i=head1[p];i;i=nxt1[i]) {
if(!v[to1[i]])
dfs1(to1[i]);
}
s[++tot]=p;
}
void dfs2(int p) {
scc[p]=sc;
t[sc]++;
for(int i=head2[p];i;i=nxt2[i]) {
if(!scc[to2[i]])
dfs2(to2[i]);
}
}
void kosa() {
for(int i=1;i<=n;i++)
if(!v[i])
dfs1(i);
for(int i=n;i>=1;i--) {
if(!scc[s[i]]) {
sc++;
dfs2(s[i]);
}
}
}
int main() {
cin>>n>>m;
while(m--) {
int u,v;
cin>>u>>v;
add1(u,v);
add2(v,u);
}
kosa();
for(int i=1;i<=n;i++) {
for(int j=head1[i];j;j=nxt1[j]) {
int y=to1[j];
if(scc[i]==scc[y])
continue;
vis[scc[i]]=true;
continue;
}
}
for(int i=1;i<=n;i++)
if(!scc[i]) {
cout<<0<<endl;
return 0;
}
for(int i=1;i<=sc;i++)
if(!vis[i]) {
ans+=t[i];
if(f==true) {
cout<<0<<endl;
return 0;
}
f=true;
}
cout<<ans;
return 0;
}
标签:连通,int,void,++,HAOI2006,cnt2,cnt1,cnt,受欢迎 来源: https://www.cnblogs.com/wyc06/p/12808175.html