题目大意
约翰的N(2≤N≤10000)只奶牛非常兴奋,因为这是舞会之夜!她们穿上礼服和新鞋子,别上鲜花,她们要表演圆舞.
只有奶牛才能表演这种圆舞.圆舞需要一些绳索和一个圆形的水池.奶牛们围在池边站好,顺时针顺序由1到N编号.每只奶牛都面对水池,这样她就能看到其他的每一只奶牛.为了跳这种圆舞,她们找了M(2≤M≤50000)条绳索.若干只奶牛的蹄上握着绳索的一端,绳索沿顺时针方绕过水池,另一端则捆在另一些奶牛身上.这样,一些奶牛就可以牵引另一些奶牛(牵引是单向的).有的奶牛可能握有很多绳索,也有的奶牛可能一条绳索都没有握。比如说贝茜,她的圆舞跳得是否成功,可以这样检验:沿着她牵引的绳索,找到她牵引的奶牛,再沿着这只奶牛牵引的绳索,又找到一只被牵引的奶牛,如此下去,若最终能回到原位,则她的圆舞跳得成功,因为这一个环上的奶牛可以逆时针牵引而跳起旋转的圜舞.如果不能回到原位,那她的圆舞是不成功的.
如果两只成功跳圆舞的奶牛有绳索相连,那她们可以同属一个组合.
给出每一条绳索的描述,请找出,成功跳了圆舞的奶牛有多少个组合?
输入数据:
第一行:两个空格分隔的整数:N和M
以下M行,每行包含两个空格分隔的整数A和B描述一根绳子从牛A牵引牛B顺时针方向。
输出数据:
一个整数,表示成功跳圆舞的团体数量
样例输入
5 4
2 4
3 5
1 2
4 1
样例输出
1
题目分析:
求的是有多少个大于等于2的强联通分量;
ACcode
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
using namespace std;
const int maxn = 10000 + 10;
vector <int> G[maxn];
int pre[maxn], lowlink[maxn], in_stack[maxn], dfs_clock, scc_cnt, ans, tot;
stack <int> S;
void dfs(int u) {
pre[u] = lowlink[u] = ++dfs_clock;
in_stack[u] = 1;
S.push(u);
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if(pre[v] == -1) {
dfs(v);
lowlink[u] = min(lowlink[u], lowlink[v]);
}
else if(in_stack[v]) {
lowlink[u] = min(lowlink[u], pre[v]);
}
}
if(lowlink[u] == pre[u]) {
//scc_cnt++;
//printf("*************\n");
tot = 0;
for(;;) {
int x = S.top(); S.pop();
tot++;
in_stack[x] = 0;
if(x == u) break;
}
//printf("%d %d\n", u, tot);
if(tot >= 2)ans++;
}
}
void find_scc(int n) {
dfs_clock = scc_cnt = 0;
//memset(sccno, 0, sizeof(sccno));
memset(pre, -1, sizeof(pre));
memset(in_stack, 0, sizeof(in_stack));
for(int i = 0; i < n; i++)
if(pre[i] == -1) dfs(i);
}
int main(){
int u, v, n, m;
scanf("%d %d", &n, &m);
while(scanf("%d %d", &u, &v) != EOF){
G[u].push_back(v);
//n = max(n, max(u, v));
}
//cout<< G[2][0] <<endl;
//cout<< n << endl;
find_scc(n);
cout<< ans << endl;
return 0;
}