给一个无向图,要求变成强连通的有向图,需要保留哪些边。
边的双连通,对于桥保留两条边,其他的只保留一条边。求双连通的过程中记录保留边。
/********************************************* Problem: 1515 User: G_lory Memory: 232K Time: 32MS Language: C++ Result: Accepted **********************************************/ #include <cstdio> #include <cstring> #include <iostream> #define pk printf("KKK!\n"); using namespace std; const int N = 1005; const int M = N * N; struct Edge { int from, to, next; int cut; } edge[M]; int cnt_edge; int head[N]; void add_edge(int u, int v) { edge[cnt_edge].from = u; edge[cnt_edge].to = v; edge[cnt_edge].next = head[u]; edge[cnt_edge].cut = 0; head[u] = cnt_edge++; } int dfn[N]; int idx; int low[N]; int n, m; void tarjan(int u, int pre) { dfn[u] = low[u] = ++idx; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (edge[i].cut) continue; edge[i].cut = 1; edge[i ^ 1].cut = -1; if (v == pre) continue; if (!dfn[v]) { tarjan(v, u); low[u] = min(low[u], low[v]); if (dfn[u] < low[v]) edge[i].cut = edge[i ^ 1].cut = 1; } else low[u] = min(low[u], dfn[v]); } } void init() { idx = cnt_edge = 0; memset(dfn, 0, sizeof dfn); memset(head, -1, sizeof head); } void solve() { for (int i = 0; i < cnt_edge; ++i) if (edge[i].cut == 1) printf("%d %d\n", edge[i].from, edge[i].to); } int main() { //freopen("in.txt", "r", stdin); int cas = 0; while (~scanf("%d%d", &n, &m)) { if (n == 0 && m == 0) break; printf("%d\n\n", ++cas); int u, v; init(); for (int i = 0; i < m; ++i) { scanf("%d%d", &u, &v); add_edge(u, v); add_edge(v, u); } tarjan(1, -1); solve(); printf("#\n"); } return 0; }
时间: 2024-12-27 18:50:36