您的位置:首页 > 其它

uva 610 - Street Directions(双联通)

2015-09-12 22:17 375 查看
题目链接:uva 610 - Street Directions

求出所有边双联通分量,然后每一块单独考虑即可。

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;
typedef pair<int,int> pii;
const int maxn = 1005;
const int maxm = 1e6;

int N, M, E, first[maxn], jump[maxm], link[maxm], vis[maxm];
int cntlock, pre[maxn], low[maxn], iscut[maxm];

void dfs (int u, int fa) {
pre[u] = low[u] = ++cntlock;

for (int i = first[u]; i != -1; i = jump[i]) {
int v = link[i];
if (!pre[v]) {
dfs(v, u);
low[u] = min(low[u], low[v]);
if (low[v] > pre[u])
iscut[i] = 1;
} else if (pre[v] < pre[u] && v != fa)
low[u] = min(low[u], pre[v]);
}
}

void findEdge () {
cntlock = 0;
memset(pre, 0, sizeof(pre));
memset(iscut, 0, sizeof(iscut));
for (int i = 1; i <= N; i++)
if (!pre[i]) dfs(i, -1);
}

inline void addEdge (int u, int v) {
jump[E] = first[u];
link[E] = v;
first[u] = E++;
}

void init () {
E = 0;
memset(first, -1, sizeof(first));

int u, v;
while (M--) {
scanf("%d%d", &u, &v);
addEdge(u, v);
addEdge(v, u);
}
findEdge();
}

void put (int u) {
if (pre[u]) return;

pre[u] = ++cntlock;

for (int i = first[u]; i != -1; i = jump[i]) {
int v = link[i];
if (iscut[i]) {
printf("%d %d\n", u, v);
continue;
}
if (vis[i]) continue;
vis[i] = vis[i^1] = 1;
printf("%d %d\n", u, v);
put(v);
}
}

void solve () {
cntlock = 0;
memset(pre, 0, sizeof(pre));
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= N; i++)
put(i);
}

int main () {
int cas = 1;
while (scanf("%d%d", &N, &M) == 2 && N + M) {
init();
printf("%d\n\n", cas++);
solve();
printf("#\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: