您的位置:首页 > 其它

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

2014-09-01 11:22 253 查看


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
, low
, dfs_clock;

vector<Edge> g
;
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
;

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
;

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: