poj2186

Tarjan模板题。建议采用二维vector存储。

学习Tarjan时要注意两个数组:

int DFN[M];                  //深度优先搜索访问次序 
int Low[M];                  //能追溯到的最早的次序 

这是学习的网址:http://www.nocow.cn/index.php/Tarjan算法

P.s. Tarjan真心是递归之精髓的体现啊!

下面是标准的Tarjan的模板。

这道题算法其实很清楚,把图的边反向存储,再把图的强连通分量求出来,然后找出入度为零的分量,如果入度为0的强连通分量个数大于1,那么最终解一定是0,否则最终解就是那个入度为零的强连通分量的点的个数。

#include <iostream>
#include <string.h>
#include <vector>

#define MAX_N 10010
#define MAX_M 50010

using namespace std;

vector <int> vec[MAX_N];

int dfn[MAX_N], low[MAX_N], stap[MAX_N], belong[MAX_N];
int n, m, bcnt, dindex = 0, stop = 0;
int rd[MAX_N], rd0cnt;
bool instack[MAX_N];

int x[MAX_M], y[MAX_M];

void tarjan(int v) {
	int u, l = vec[v].size();
	dfn[v] = low[v] = ++dindex;
	instack[v] = true;
	stap[++stop] = v;
	for (int i = 0; i < l; i++) {
		u = vec[v][i];
		if (!dfn[u]) {
			tarjan(u);
			if (low[u] < low[v])
				low[v] = low[u];
		}
		else if (instack[u] && dfn[u] < low[v])
			low[v] = dfn[u];
	}
	if (dfn[v] == low[v]) {
		bcnt++;
		do {
			u = stap[stop--];
			instack[u] = false;
			belong[u] = bcnt;
		}
		while (u != v);
	}
}

int main() {
	while (cin >> n >> m) {
		for (int i = 1; i <= m; i++) {
			cin >> x[i] >> y[i];
			vec[y[i]].push_back(x[i]);
		}
		stop = bcnt = dindex = 0;
		memset(dfn, 0, sizeof(dfn));
		for (int i = 1; i <= n; i++)
			if (!dfn[i]) tarjan(i);
		memset(rd, 0, sizeof(rd));
		for (int i = 1; i <= m; i++)
			if (belong[x[i]] != belong[y[i]])
				rd[belong[x[i]]]++;
		int cnt = 0;
		for (int i = 1; i <= bcnt; i++)
			if (rd[i] == 0) cnt++;
		if (cnt > 1) cout << 0 << endl;
		else {
			cnt = 0;
			for (int i = 1; i <= n; i++)
				if (rd[belong[i]] == 0) cnt++;
			cout << cnt << endl;
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值