演算法整理 & 複習:割點、割邊
阿新 • • 發佈:2020-12-14
文章目錄
一、割點(割頂)
#include <stdio.h>
#include <iostream>
using namespace std;
#define MAXN 200005
int n,m;
int cnt,flag;
int head[MAXN];
int dfn[MAXN],low[MAXN],cut[MAXN];
struct node{
int to,next;
}map[MAXN];
void add(int u,int v){
map[++cnt] = (node){v,head[u]};
head[u] = cnt;
}
void tarjan(int u, int root){
dfn[u] = low[u] = ++flag;
int cur = 0;
for(int k=head[u];k;k=map[k].next){
int v = map[k].to;
if(!dfn[v]){
++cur;
tarjan(v,root);
low[u] = min(low[u],low[v]);
if((u==root && cur> 1) || (u!=root && dfn[u]<=low[v])) cut[u] = 1;
}
else low[u] = min(low[u],dfn[v]);
}
}
int main(void){
cin >> n >> m;
for(int i=1;i<=m;i++){
int u,v;
cin >> u >> v;
add(u,v);
add(v,u);
}
for(int i=1;i<=n;i++){
tarjan(i,i);
}
int ans = 0;
for (int i=1;i<=n;i++){
if(cut[i]) ans++;
}
cout << ans << endl;
for(int i=1;i<=n;i++){
if(cut[i]) cout << i << " ";
}
return 0;
}
二、割邊(橋)
tarjan(int u){
dfn[u] = low[u] = ++flag;
for(int k=head[u];k;k=map[k].next){
int v = map[k].to;
if(!dfn[v]){
tarjan(v);
low[u] = min(low[u],low[v]);
if(dfn[u] < low[v]) cut[k] = 1; // 這裡記的是邊的序號
}
else low[u] = min(low[u],dfn[v]);
}
}
返回