强联通分量

这类题目普遍有个共性就是缩点,算法模板,核心的部分就是缩点,理解比价抽象,不过还行。

有两种算法可以用,我个人倾向于第一种算法Tarjan 这个算法一次性遍历,而且变化很多联通性的问题都可以用这个算法的构架加上变形解决

举个例子 poj2186

/*
* this code is made by LinMeiChen
* Problem:
* Type of Problem:
* Thinking:
* Feeling:
*/
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<list>
using namespace std;
typedef long long lld;
typedef unsigned int ud;
#define oo 0x3f3f3f3f
#define maxn 10010
#define maxm 50010
struct Edge
{
	int v, next;
}E[maxm<<1];
int head[maxn], tol;
int low[maxn], dfn[maxn];
int mark[maxn], stack[maxn];
int top, num, n, m;
int id[maxn], inout[maxn];
int U[maxm], V[maxm];

void Init()
{
	memset(low, 0, sizeof low);
	memset(mark, 0, sizeof mark);
	memset(dfn, 0, sizeof dfn);
	memset(head, -1, sizeof head);
	memset(inout, 0, sizeof inout);
	tol = 0;
	num = 0;
	top = 0;
}

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

void Tarjan(int u, int dep)
{
	
	mark[u] = 1;
	low[u] = dfn[u] = dep;
	stack[top++] = u;
	int v, Min = oo;
	for (int i = head[u]; i != -1; i = E[i].next)
	{	
		v = E[i].v;   //printf("%d %d %d\n", u, v, i);
		if (!mark[v])
			Tarjan(v, dep + 1);
		Min = min(Min, low[v]);
	}
	if (Min < low[u])
	{
		low[u] = Min;
		return;
	}
	++num;
	do
	{
		id[v = stack[--top]] = num;
		low[v] = n;
	} while (u != v);
}

void Reach()
{
	for (int i = 1; i <= n;i++)
	if (!mark[i])
		Tarjan(i, 1);
}

bool Find()
{
	int pos = 1;
	for (int i = 1; i <= m; i++)
	{
		int u = id[U[i]];
		int v = id[V[i]];
		if (u != v)
		{
			inout[u]++;
		}
	}
	int cnt = 0;
	for (int i = 1; i <= num; i++)
	{
		if (inout[i] == 0)
		{
			pos = i;
			cnt++;
		}
	}
	if (cnt > 1)
		return false;
	
	cnt = 0;
	for (int i = 1; i <= n; i++)
	{
		if (id[i] == pos)
			cnt++;
	}
	printf("%d\n", cnt);
	return true;
}

int main()
{
	int u, v;
	while (scanf("%d%d", &n, &m) != EOF)
	{
		Init();
		for (int i = 1; i <= m; i++)
		{
			scanf("%d%d", &u, &v);
			U[i] = u;
			V[i] = v;
			add_edge(u, v);
		}
		Reach(); 
		if (!Find())
			printf("0\n");
	}
}

/*
3 3
1 2
2 1
2 3
*/
/*
3 3
1 2
2 3
3 1

3 3
1 2
2 1
2 3

5 4
1 4
2 4
3 4
5 4

5 5
1 2
2 3
3 1
1 4
4 5

5 6
1 2
2 3
3 1
1 4
4 5
5 3

2 2
1 2
2 1

3 2
1 2
2 1

6 6
1 2
2 3
3 1
1 4
4 5
5 3

5 6
1 2
2 3
3 1
1 4
4 5
5 4

5 7
4 1
1 2
2 3
3 1
1 4
4 5
5 4

5 6
1 2
2 3
3 1
1 4
4 5
5 1

7 9
1 2
2 3
3 1
4 5
5 6
6 4
4 7
7 1
1 7

6 6
1 2
2 3
3 1
4 5
5 6
6 4

4 4
1 2
2 3
3 1
1 4

4 4
1 2
2 3
3 1
4 1

5 6
1 2
2 3
3 1
5 1
5 4
3 4

7 9
1 2
2 3
3 1
5 1
5 4
3 4
4 7
7 6
6 4
*/

你可能感兴趣的:(算法,网络,poj)