版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pengwill97/article/details/81951540
题意
给出无向图,求出图中的割边与割点。
题解
Tarjan算法。
代码
#include<bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 1e6+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int n, m;
int head[nmax], tot, dfs_clock;
int dfn[nmax], low[nmax];
bool iscut[nmax];
struct edge{
int to, nxt;
}e[nmax<<1];
void add_edge(int u, int v) {
e[tot].to = v;
e[tot].nxt = head[u];
head[u] = tot ++;
}
typedef pair<int, int> pii;
bool cmp(pii a, pii b) {
if(a.first == b.first)
return a.second < b.second;
else
return a.first < b.first;
}
vector<int> cp;
vector<pair<int, int> > cedge;
void get_cut(int u, int fa) {
dfn[u] = low[u] = ++dfs_clock;
int child = 0;
for(int i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].to;
if(!dfn[v]) {
child ++;
// printf("debug %d %d\n", u, v);
get_cut(v, u);
low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u]) {
if(!iscut[u] && fa != -1) {
cp.push_back(u);
iscut[u] = true;
}
}
if(low[v] > dfn[u]) {
if(u < v)
cedge.push_back(make_pair(u,v));
else
cedge.push_back(make_pair(v,u));
}
} else if(v != fa) {
low[u] = min(low[u], dfn[v]);
}
}
if(fa == -1 && child > 1) {
iscut[u] = true;
cp.push_back(u);
}
}
int main(){
memset(head, -1, sizeof head);
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; ++i) {
int u, v;
scanf("%d %d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
for(int i = 1; i <= n; ++i) {
if(!dfn[i])
get_cut(i,-1);
}
// for(int i = 1; i <= n; ++i) {
// printf("%d ", dfn[i]);
// }
// printf("\n");
// for(int i = 1; i <= n; ++i) {
// printf("%d ", low[i]) ;
// }
// printf("\n");
sort(cp.begin(), cp.end());
sort(cedge.begin(), cedge.end(), cmp);
if(cp.size() == 0) {
printf("Null\n");
} else {
for(int i = 0; i < cp.size(); ++i) {
printf("%d ",cp[i]);
}
printf("\n");
}
for(int i = 0; i < cedge.size(); ++i) {
printf("%d %d\n",cedge[i].first, cedge[i].second);
}
return 0;
}