約翰的N (2 <= N <= 10,000)隻奶牛非常興奮,因為這是舞會之夜!她們穿上禮服和新鞋子,别 上鮮花,她們要表演圓舞.
隻有奶牛才能表演這種圓舞.圓舞需要一些繩索和一個圓形的水池.奶牛們圍在池邊站好, 順時針順序由1到N編号.每隻奶牛都面對水池,這樣她就能看到其他的每一隻奶牛.
為了跳這種圓舞,她們找了 M(2<M< 50000)條繩索.若幹隻奶牛的蹄上握着繩索的一端, 繩索沿順時針方繞過水池,另一端則捆在另一些奶牛身上.這樣,一些奶牛就可以牽引另一些奶 牛.有的奶牛可能握有很多繩索,也有的奶牛可能一條繩索都沒有.
對于一隻奶牛,比如說貝茜,她的圓舞跳得是否成功,可以這樣檢驗:沿着她牽引的繩索, 找到她牽引的奶牛,再沿着這隻奶牛牽引的繩索,又找到一隻被牽引的奶牛,如此下去,若最終 能回到貝茜,則她的圓舞跳得成功,因為這一個環上的奶牛可以逆時針牽引而跳起旋轉的圓舞. 如果這樣的檢驗無法完成,那她的圓舞是不成功的.
如果兩隻成功跳圓舞的奶牛有繩索相連,那她們可以同屬一個組合.
給出每一條繩索的描述,請找出,成功跳了圓舞的奶牛有多少個組合?
輸入格式
Line 1: Two space-separated integers: N and M
Lines 2…M+1: Each line contains two space-separated integers A and B that describe a rope from cow A to cow B in the clockwise direction.
輸出格式
Line 1: A single line with a single integer that is the number of groups successfully dancing the Round Dance.
輸入輸出樣例
輸入 #1
5 4
2 4
3 5
1 2
4 1
輸出 #1
1
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn = 100005*2;
int n,m;
int head[maxn],tot;
int dfn[maxn],low[maxn],Stack[maxn],num[maxn];
bool vis[maxn];
int top,cnt,ans;
struct node
{
int to,next;
}a[maxn];
void add(int x,int y)
{
a[tot].to = y;
a[tot].next = head[x];
head[x] = tot++;
}
void tarjan(int u)
{
int v;
low[u] = dfn[u] = ++cnt;
Stack[top++] = u;
vis[u] = true;
for(int i=head[u]; i != -1; i=a[i].next)
{
v = a[i].to;
if(!dfn[v])
{
tarjan(v);
low[u] = min(low[u],low[v]);
}
else
{
if(vis[v])
low[u] = min(low[u],low[v]);
}
}
if(low[u] == dfn[u])
{
ans++;
do
{
v = Stack[--top];
vis[v] = false;
num[ans]++;//記錄每個強連通分量有多少個點
}
while(v != u);
}
}
void solve()
{
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(vis,false,sizeof(vis));
memset(num,0,sizeof(num));
top = ans = cnt = 0;
for(int i=1; i<=n; i++)
{
if(!dfn[i])
tarjan(i);
}
}
int main()
{
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));
tot = 0;
for(int i=1; i<=m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
}
solve();
int k = 0;
for(int i=1; i<=n; i++)
{
if(num[i] > 1)
k++;
}
printf("%d",k);
}