1. 程式人生 > >hihor 學習日記:hiho一下 第五十二週 (割邊與割點)

hihor 學習日記:hiho一下 第五十二週 (割邊與割點)

http://hihocoder.com/contest/hiho52/problem/1

題意:

這道題就是求割邊與割點,

割邊與割點

在這裡插入圖片描述

思路:

在這裡插入圖片描述
在這裡插入圖片描述
大致就是用DFS樹來得到low,與dfn比較來判斷當前點的子樹上的點是否與當前點的父點相連,如果不聯,那麼去掉當前點,子樹與原來的樹不再連通,這就是割點。
而割邊相同,如果當前點的子樹上的點不與當前點以及當前點的父點相連,那麼當前點與子樹相連的邊就是割邊

注意:

這道題的割點有可能有相同的,所以最後輸出是要去重

AC程式碼:

#include <bits/stdc++.h>

using namespace std;
#define LL long long const int Mod = 1e9 + 7; const int maxn = 1e5 + 5; const double eps = 0.00000001; const int INF = 0x3f3f3f3f; struct Edge{ int v, next; bool friend operator < (Edge a, Edge b) { if(a.v == b.v) return a.next < b.next; return a.v < b.v; } }edge[maxn <<
1], edge2[maxn], edge3[maxn]; int tot1, tot2, tot3, head[maxn]; int vis[maxn], low[maxn], par[maxn], dfn[maxn]; void init() { tot1 = tot2 = tot3 = 0; memset(head, -1, sizeof(head)); memset(vis, 0, sizeof(vis)); memset(par, -1, sizeof(par)); } void addEdge(int u, int v) { edge[
tot1].v = v; edge[tot1].next = head[u]; head[u] = tot1 ++; edge[tot1].v = u; edge[tot1].next = head[v]; head[v] = tot1 ++; } void dfs(int u) { static int counter = 0; int child = 0; vis[u] = 1; dfn[u] = low[u] = ++counter; for (int i = head[u]; i + 1; i = edge[i].next) { int v = edge[i].v; if(!vis[v]) { child ++; par[v] = u; dfs(v); low[u] = min(low[u], low[v]); if(par[u] == -1 && child > 1) edge2[tot2 ++].v = u; if(par[u] != -1 && low[v] >= dfn[u]) edge2[tot2 ++].v = u; if(low[v] > dfn[u]) { edge3[tot3].v = min(u, v); edge3[tot3 ++].next = max(u, v); } } else if(v != par[u]){ low[u] = min(low[u], dfn[v]); } } } int main() { init(); int N, M; cin >> N >> M; while(M --) { int u, v; cin >> u >> v; addEdge(u, v); } dfs(1); sort(edge2, edge2 + tot2); sort(edge3, edge3 + tot3); if(tot2) { cout << edge2[0].v; for (int i = 1; i < tot2; i ++) if(edge2[i].v != edge2[i - 1].v) cout << " " << edge2[i].v; }else cout << "Null\n"; cout << endl; for (int i = 0; i < tot3; i ++) cout << edge3[i].v << " " << edge3[i].next << endl; return 0; }