天天看點

求點大于1的強連通分量數量

約翰的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);
}

           

繼續閱讀