现在的位置: 首页 > 综合 > 正文

poj 1523 SPF 求割点

2014年07月08日 ⁄ 综合 ⁄ 共 1511字 ⁄ 字号 评论关闭

题目大意:求一个无向图的割点,并把割点连接的连通个数求出来

解题思路:tarjan算法求割点

这里定义:

Low(u)为u或u的子树中能通过非父子边追溯到的最早的节点,即DFS序号最小的节点。根据定义,则有:

Low(u)=Min
{
DFS(u)
DFS(v) (u,v)为后向边(返祖边) 等价于 DFS(v)<DFS(u)且v不为u的父亲节点
Low(v) (u,v)为树枝边(父子边)
}

满足割点的条件有:

一个顶点u是割点,当且仅当满足(1)或(2)
(1) u为树根,且u有多于一个子树。
(2) u不为树根,且满足存在(u,v)为树枝边(或称父子边,即u为v在搜索树中的父亲),使得DFS(u)<=Low(v)。

 

所以用一个cnt[i]保存i点连接的连通分量个数

由于0作为根节点,所以cnt[0] = 0;

其他节点初始化为1

当dfs[u] <= low[v]时,(u,v)为树枝边,cnt[u]++

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

struct node
{
	int v, next;
};

const int maxn = 1010;

int head[maxn], e, index, num, cnt[maxn], dfn[maxn], low[maxn];
node edge[maxn * maxn];

void addEdge(int u, int v);
void init();
void tarjan(int u);

int main()
{
	int u, v, t = 0;
	init();
	while(scanf("%d", &u) != EOF && u != 0)
	{
		t++;
		scanf("%d", &v);
		u--; v--;
		addEdge(u, v);
		num = max(num, max(u, v));
		while(scanf("%d", &u) != EOF && u != 0)
        {
            scanf("%d", &v);
            num = max(num, max(u, v));
            u--; v--;
            addEdge(u, v);
        }
        cnt[0] = 0;
        for(int i = 1; i < num; i++)
        	cnt[i] = 1;
        tarjan(0);
        printf("Network #%d\n", t);
        bool flag = false;
        for(int i = 0; i < num; i++)
        {
			if(cnt[i] > 1)
			{
				flag = true;
				printf("  SPF node %d leaves %d subnets\n", i + 1, cnt[i]);
			}
		}
		if(!flag)
			printf("  No SPF nodes\n");
		printf("\n");
		init();
	}
		return 0;
}

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

void init()
{
	memset(head, -1, sizeof(head));
	memset(dfn, -1, sizeof(dfn));
	e = 0;
	index = 0;
	num = 0;
}

void tarjan(int u)
{
	dfn[u] = low[u] = index++;
	for(int i = head[u]; i != -1; i = edge[i].next)
	{
		int v = edge[i].v;
		if(dfn[v] == -1)
		{
			tarjan(v);
			if(dfn[u] <= low[v])
				cnt[u]++;
			else
				low[u] = min(low[u], low[v]);
		}
		else
			low[u] = min(low[u], dfn[v]);
	}
}

 

抱歉!评论已关闭.