牛的舞会
Popular Cows
USACO06JAN
The Cow Prom
#include <bits/stdc++.h>
using namespace std;
const int N=10001,M=100010;
int n,m,ans,pos,a,b,cnt,id,head[N],low[N],dfn[N];
stack<int>S;//定义一个栈
struct edge{//结构体,存储编号与下一个
int to,next;
}e[M];
void add(int a,int b){//链式前向星构图
pos++;
e[pos].to=b;
e[pos].next=head[a];
head[a]=pos;
}
bool in[N];
void tarjan(int u){
dfn[u]=low[u]=++id;
S.push(u);//入栈
in[u]=true;//是否在栈中
for(int i=head[u];i;i=e[i].next){//(dijkstra)遍历
int v=e[i].to;//下一个访问的点
if(in[v])
low[u]=min(low[u],dfn[v]);//判断u是否为v的子节点
else{
tarjan(v);
low[u]=min(low[u],low[v]);
}
}
if(low[u]==dfn[u]){//构成强连通分量
int v,num=0;
cnt++;//强连通分量的个数+1
while(v!=u){//清空
v=S.top();
S.pop();
in[v]=false;//不在栈中
num++;
}
if(num!=1)//存在强连通分量
ans++;//答案加1
}
}
int main(){
scanf("%d%d",&n,&m);//输入n,m
for(int i=1;i<=m;i++){//循环输入
scanf("%d%d",&a,&b);//输入a,b
add(a,b);//构图
}
for(int i=1;i<=n;i++)
if(!dfn[i])//如果还未访问过
tarjan(i);//访问
printf("%d\n",ans);//输出最后的答案
return 0;//结束
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <list>
#include <set>
#include <functional>
#include <stack>
using namespace std;
const int N=10001,M=100010;
int n,m,ans,pos,a,b,cnt,id,head[N],low[N],dfn[N];
stack<int>S;//定义一个栈
struct edge{//结构体,存储编号与下一个
int to,next;
}e[M];
void add(int a,int b){//链式前向星构图
pos++;
e[pos].to=b;
e[pos].next=head[a];
head[a]=pos;
}
bool in[N];
void tarjan(int u){
dfn[u]=low[u]=++id;
S.push(u);//入栈
in[u]=true;//是否在栈中
for(int i=head[u];i;i=e[i].next){//(dijkstra)遍历
int v=e[i].to;//下一个访问的点
if(in[v])
low[u]=min(low[u],dfn[v]);//判断u是否为v的子节点
else{
tarjan(v);
low[u]=min(low[u],low[v]);
}
}
if(low[u]==dfn[u]){//构成强连通分量
int v,num=0;
cnt++;//强连通分量的个数+1
while(v!=u){//清空
v=S.top();
S.pop();
in[v]=false;//不在栈中
num++;
}
if(num!=1)//存在强连通分量
ans++;//答案加1
}
}
int main(){
scanf("%d%d",&n,&m);//输入n,m
for(int i=1;i<=m;i++){//循环输入
scanf("%d%d",&a,&b);//输入a,b
add(a,b);//构图
}
for(int i=1;i<=n;i++)
if(!dfn[i])//如果还未访问过
tarjan(i);//访问
printf("%d\n",ans);//输出最后的答案
return 0;//结束
}