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

时间:2023-03-09 07:01:06
UVA 10972 - RevolC FaeLoN(边-双连通分量)

UVA 10972 - RevolC FaeLoN

option=com_onlinejudge&Itemid=8&page=show_problem&category=547&problem=1913&mosmsg=Submission+received+with+ID+14127122" target="_blank" style="">题目链接

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

思路:先求出边-双连通分量,每一个连通分量都能定向,然后缩点。转化为欧拉回路,假设每一个点度数都是大于等于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;
}