POJ 3180 The Cow Prom

POJ 3180

题目大意

约翰的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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值