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;
}