hihor 學習日記:hiho一下 第五十二週 (割邊與割點)
阿新 • • 發佈:2018-12-30
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;
}