• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

  • 联系
  • 订阅
  • 管理

View Post

poj 2186 Popular Cows 强连通分量tarjan算法

//第一次用Tarjan求强连通分量
//先求强连通分量,再重新构图,找出度为0的点,并且出度为0的点只有1个
//这题不能求入度,不能判断重新构图后的点的入度为n-1
//因为存在单链的情况,这时,链尾的点就是答案,但是该入度为1
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int N = 10005;
const int M = 50005;

struct Edge
{
	int v;
	int next;
};

int head[N];
Edge edge[M];
int n, m;
int cnt_edge;

void add_edge(int u, int v)
{	
	edge[cnt_edge].next = head[u];
	edge[cnt_edge].v = v;
	head[u] = cnt_edge++;
}

int scc_head[N];
Edge scc_edge[N];
int cnt_scc_edge;

void add_edge2(int u, int v)
{
	scc_edge[cnt_scc_edge].next = scc_head[u];
	scc_edge[cnt_scc_edge].v = v;
	scc_head[u] = cnt_scc_edge++;
}

int cnt_scc_node;
int Stack[N];
int low[N], dfn[N], outdegree[N];
int Index,top;
bool in_stack[N];
int belong[N];
int scc_node_size[N];

void tarjan(int u)
{
	dfn[u] = low[u] = ++Index;
	Stack[top++] = u;
	in_stack[u] = true;
	for (int i = head[u]; i != -1; i = edge[i].next)
	{
		int v = edge[i].v;
		if (!dfn[v])
		{
			tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if (in_stack[v])
			low[u] = min(low[u], dfn[v]);
	}

	if (dfn[u] == low[u])
	{	
		int j;
		do{
			j = Stack[--top];
			in_stack[j] = false;
			scc_node_size[cnt_scc_node]++;
			belong[j] = cnt_scc_node;
		}while (u != j);
		cnt_scc_node++;	
	}
}

int main()
{
	int a, b;
	while (scanf("%d%d", &n, &m) != EOF)
	{
		cnt_edge = 0;
		memset(head, -1, sizeof(head));
		for (int i = 0; i < m; i++)
		{
			scanf("%d%d", &a, &b);
			add_edge(a, b);
		}

		memset(dfn, 0, sizeof(dfn));
		memset(in_stack, false, sizeof(in_stack));
		Index = 0;
		cnt_scc_node = 0;
		top = 0;

		memset(scc_node_size, 0, sizeof(scc_node_size));
		for (int i = 1; i <= n; i++)
			if (!dfn[i])
				tarjan(i);

		//重新构图,求出度为0的点
		memset(scc_head, -1, sizeof(scc_head));
		cnt_scc_edge = 0;

		for (int i = 1; i <= n; i++)
			for (int j = head[i]; j != -1 ; j = edge[j].next)
			{
				int v = edge[j].v;
				if (belong[i] != belong[v])
					add_edge2(belong[i], belong[v]);
			}

		memset(outdegree, 0, sizeof(outdegree));
		for (int i = 0; i < cnt_scc_node; i++)
			for (int j = scc_head[i]; j != -1; j = scc_edge[j].next)					
				outdegree[i]++;

		int ans = 0;
		int ans_count = 0;
		for (int i = 0; i < cnt_scc_node; i++)
			if (outdegree[i] == 0)
			{
				ans = scc_node_size[i];
				ans_count++;
			}

		if (ans_count == 1)
			printf("%d\n", ans);
		else
			printf("0\n");
	}
	return 0;
}

posted on 2011-04-22 22:25  sysuwhj  阅读(554)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3