码迷,mamicode.com
首页 > 其他好文 > 详细

UVA 10972 - RevolC FaeLoN(边-双连通分量)

时间:2017-04-22 13:12:10      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:ems   void   sms   注意   php   链接   ssi   ace   个数   

UVA 10972 - RevolC FaeLoN

题目链接

题意:给定一个无向图(不一定全连通)。如今把边定向,问还要加入几条边使得图强连通

思路:先求出边-双连通分量,每一个连通分量都能定向,然后缩点。转化为欧拉回路,假设每一个点度数都是大于等于2的偶数就是回路,也就是强连通了,所以计算度数为0和1的个数。一条边能添加两个度数。所以答案为所以仅仅要再加入上(a + 1) / 2 + b条边就能够了。注意特判一開始就已经是边-双连通分量的情况。答案应该为0

代码:

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

const int N = 1005;

struct Edge {
	int u, v, id;
	int fan;
	bool iscut, used;
	Edge() {}
	Edge(int u, int v, int id, int fan) {
		this->u = u;
		this->v = v;
		this->id = id;
		this->fan = fan;
		used = false;
		iscut = false;
	}
};

int pre[N], low[N], dfs_clock;

vector<Edge> g[N];
vector<Edge> cut;

int dfs(int u, int fa) {
	int lowu = pre[u] = ++dfs_clock;
	for (int i = 0; i < g[u].size(); i++) {
		int v = g[u][i].v;
		int id = g[u][i].id;
		if (id == fa) continue;
		if (!pre[v]) {
			int lowv = dfs(v, id);
			lowu = min(lowu, lowv);
			if (lowv > pre[u]) {
				cut.push_back(g[u][i]);
				g[u][i].iscut = true;
				g[v][g[u][i].fan].iscut = true;
			}
		} else lowu = min(lowu, pre[v]);
	}
	return low[u] = lowu;
}

int bcc_cnt, bccno[N];

void dfs2(int u, int bcc_cnt) {
	bccno[u] = bcc_cnt;
	for (int i = 0; i < g[u].size(); i++) {
		if (g[u][i].iscut) continue;
		int v = g[u][i].v;
		if (bccno[u] == bccno[v]) continue;
		dfs2(v, bcc_cnt);
	}
}

void find_cut(int n) {
	cut.clear();
	memset(pre, 0, sizeof(pre));
	dfs_clock = 0;
	for (int i = 0; i < n; i++) {
		if (!pre[i]) {
			dfs(i, 0);
		}
	}
}

void find_bcc(int n) {
	find_cut(n);
	bcc_cnt = 0;
	memset(bccno, 0, sizeof(bccno));
	for (int i = 0; i < n; i++) {
		if (bccno[i]) continue;
		dfs2(i, ++bcc_cnt);
	}
}

int n, m, du[N];

int main() {
	while (~scanf("%d%d", &n, &m)) {
		for (int i = 0; i < n; i++) g[i].clear();
		int u, v;
		for (int i = 1; i <= m; i++) {
			scanf("%d%d", &u, &v);
			u--; v--;
			g[u].push_back(Edge(u, v, i, g[v].size()));
			g[v].push_back(Edge(v, u, i, g[u].size() - 1));
		}
		find_bcc(n);
		if (bcc_cnt == 1) {
			printf("0\n");
			continue;
		}
		memset(du, 0, sizeof(du));
		for (int i = 0; i < cut.size(); i++) {
			int u = cut[i].u, v = cut[i].v;
			if (bccno[u] != bccno[v]) {
				du[bccno[u]]++; du[bccno[v]]++;
			}
		}
		int a = 0, b = 0;
		for (int i = 1; i <= bcc_cnt; i++) {
			if (du[i] == 1) a++;
			if (du[i] == 0) b++;
		}
		printf("%d\n", (a + 1) / 2 + b);
	}
	return 0;
}


UVA 10972 - RevolC FaeLoN(边-双连通分量)

标签:ems   void   sms   注意   php   链接   ssi   ace   个数   

原文地址:http://www.cnblogs.com/llguanli/p/6747037.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!