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

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;
}
时间: 2024-10-05 15:26:42

UVA 10972 - RevolC FaeLoN(边-双连通分量)的相关文章

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

题目大意:给定一个无向图,要求你把所有的无向边变成有向边,并且添加最少的有向边,使得新的有向图强连通 解题思路:这题和POJ - 3352 Road Construction 类似,只不过这题给的不一定是连通图,有可能缩点后出现孤立的点,但大体的思路是一样的 前面的就不详说了,可以看戳这里里面已经写了,这里讲一下怎么处理孤立的点 如果有n个点,要求在这n个点间添加有向边,使得这n个点变成强连通,那么需要添加的边的数量为n 有了上面这个结论,求的时候就比较好办了,处理的时候,只需要统计出所有度为1

uva 10792 无向图的边双连通分量

题意:给定一个无向图,要求把所有无向边改成有向边,并且添加最少的有向边,是的新的无向图连通. 首先,这题是先要明白,有向图的强连通分量,如果把所有的边都变成无向的,就是无向图的边双连通分量. 恩,本来以为边双连通分量又是求桥又是绕过桥dfs很麻烦想想就不想做..后来无意中在别人的题解上看到一个结论(好厉害..) 方法如下: 对无向图执行dfs求割点,然后对于任意点i和j,如果low[i]==low[j],那么它们属于同一个边-双连通分量 (点-双连通分量内的两个点的low[]值不一定相同,自己画

UVA 1364 - Knights of the Round Table (找双连通分量 + 二分图染色法判断)

都特么别说话,我先A了这道题! 卧槽啊.....! 题意来自 kuangbin: 亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突, 并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有如下要求: 1.  相互憎恨的两个骑士不能坐在直接相邻的2个位置: 2.  出席会议的骑士数必须是奇数,这是为了让投票表决议题时都能有结果. 注意:1.所给出的憎恨关系一定是双向的,不存在单向憎恨关系. 2.由于是圆桌会议,则每个出席的骑士身边必定刚好有2个骑士. 即每个骑士的座位两边都

UVALive - 3523 Knights of the Round Table(无向图的双连通分量)

题目大意:有n个骑士经常举行圆桌会议,每次圆桌会议至少要有3个骑士参加(且每次参加的骑士数量是奇数个),且所有互相憎恨的骑士不能坐在圆桌旁的相邻位置,问有多少个骑士不可能参加任何一个会议 解题思路:以骑士为点建立无向图G.如果两个骑士可以相邻(即他们并不互相憎恨),即可连一条边. 则题目就转化为求不在任何一个简单奇圈上的结点个数 首先,圈就是一个双连通的分量,所以第一件事就是将所有的双连通分量求出来,接着再判定这个双连通分量是不是奇圈 奇圈的判定就是用二分图染色判定,如果某个圈能被二分图染色,那

poj 2942 Knights of the Round Table(无向图的双连通分量+二分图判定)

#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #

UVALive 3523 Knights of the Round Table(二分图+双连通分量)

Description Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, and drinking with the other knights are fun things to do. Therefore, it is not very surprising that in recent years the kingdom of King

10765 - Doves and bombs(双连通分量)

UVA 10765 - Doves and bombs 题目链接 题意:给定一个无向图,每个点的鸽子值为删去这个点后会有几个连通块,问鸽子值前m大的点的鸽子值,如果相同,按编号排 思路:就裸的双连通分量,在每个连通分量如果是割顶的点就加一,最后如果答案为0的点,答案应该是1 代码: #include <cstdio> #include <cstring> #include <vector> #include <stack> #include <algo

UVALive - 5135 Mining Your Own Business(双连通分量)

题目大意:有N个矿井 ,由一些隧道连接起来,现在要修建尽量少的安全通道,使得无论哪里发生事故,所有人均能逃出,求建的最少的安全通道数量和方案数 解题思路:建安全通道的话,肯定不能建在割顶,因为割顶如果崩塌了,割顶所连接的双连通分量内的点就跑不掉了,还得在双连通分量里面再建点(上述为双连通分量内部只有一个割顶的情况),这样不划算,还不如直接在里面建点 如果一个双连通分量的内部割顶有多个的话,那么在这个双连通分量里面就可以不用建安全通道了,因为一个割顶崩塌了,还有其他点可以连向外面,所以,只考虑内部

UVALive 5135 Mining Your Own Business 双连通分量 2011final

题意:n条隧道由一些点连接而成,其中每条隧道链接两个连接点.任意两个连接点之间最多只有一条隧道.任务就是在这些连接点中,安装尽量少的太平井和逃生装置,使得不管哪个连接点倒塌,工人都能从其他太平井逃脱,求最少安装数量和方案. 思路:其实本题就相当于在一张无向图中,涂尽量少的黑点,使得任意删除哪个点,每个连通分量至少有一个黑点.因为不同的连通分量最多只有一个公共点,那一定是割点.可以发现,涂黑割点是不划算的,而且在 一个点-双连通分量中涂黑两个黑点也是不划算的.所以只有当点-双连通分量只有一个割点时