洛谷OJ: P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm(强连通分量)

思路:求强连通分量的模版题, 答案就是结点个数大于1的强连通分量的个数

#include <iostream>
#include <vector>
#include <cstdio>
#include <stack>
#define sz size()
#define Min(a,b) a<b?a:b
using namespace std;

const int maxn = 10000+10;
//tarjan中需要使用的变量
//------------------------
stack<int> Stack;
int Deep, Sum; //Deep记录搜索了几个点, Sum记录有几个强连通分量
int Dfn[maxn], Low[maxn], Cnt[maxn], Id[maxn]; //Cnt[i]代表第i个强连通分量有几个结点, Id[i]代表结点i属于哪一个强连通分量
bool InStack[maxn];
//------------------------
vector<int> G[maxn];
int n, m, ans;

void tarjan(int cur) {
    Dfn[cur] = Low[cur] = ++Deep; //Step1
    Stack.push(cur); InStack[cur] = 1; //Step2
    for(int i = 0; i < G[cur].sz; i++) { //Step3
        int v = G[cur][i];
        if(!Dfn[v]) {
            tarjan(v);
            Low[cur] = Min(Low[cur], Low[v]);
        }
        else if(InStack[v]) {
            Low[cur] = Min(Low[cur], Low[v]);
        }
    }
    if(Dfn[cur] == Low[cur]) { //Step4
        int v;
        Id[cur] = ++Sum;
        Cnt[Sum]++;
        while((v = Stack.top()) != cur) {
            Stack.pop(); InStack[v] = 0;
            Id[v] = Sum;
            Cnt[Sum]++;
        }
        Stack.pop();
    }
}

int main() {
    int t1, t2;
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= m; i++) {
        scanf("%d %d", &t1, &t2);
        G[t1].push_back(t2);
    }
    for(int i = 1; i <= n; i++) {
        if(!Dfn[i]) {
            tarjan(i);
        }
    }
    for(int i = 1; i <= Sum; i++) {
        if(Cnt[i] > 1) {
            ans++;
        }
    }
    printf("%d\n", ans);
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值