#include<bits/stdc++.h>
using namespace std;constint mxn =2e5+10;
vector<int> e[mxn];
vector<int> cut;int low[mxn], dfn[mxn], idx;voidTarjan(int u,int root){
low[u]= dfn[u]=++ idx;int child =0;for(int i =0; i < e[u].size(); i ++){int v = e[u][i];if(! dfn[v]){Tarjan(v, root);
low[u]=min(low[u], low[v]);if(u == root) child++;elseif(low[v]>= dfn[u]) cut.push_back(u);}else low[u]=min(low[u], dfn[v]);}if(u == root && child >=2) cut.push_back(root);}voidinit(int n){
idx =0;for(int i =1; i <= n; i ++) e[i].clear(), dfn[i]=0;
cut.clear();}intmain(){int n, m;scanf("%d %d",&n,&m);init(n);int u, v;for(int i =1; i <= m; i ++){scanf("%d %d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);}for(int i =1; i <= n; i ++)if(! dfn[i])Tarjan(i, i);sort(cut.begin(), cut.end());int size =unique(cut.begin(), cut.end())- cut.begin();//⚠️ 我们可能将某个 割点 重复的 放入cut 容器,所以我们要去重printf("%d\n", size);//元素去重之后, 的输出的 下标范围也要改变for(int i =0; i < size; i ++)printf("%d ", cut[i]);printf("\n");return0;}
割边模版
#include<iostream>#include<vector>
using namespace std;constint mxn =1e5;
vector<int> e[mxn];int low[mxn], dfn[mxn], idx;
vector<pair<int,int>> cut;voidTarjan(int u,int p){
low[u]= dfn[u]=++ idx;for(int i =0; i < e[u].size(); i ++){int v = e[u][i];if(p == v)continue;if(! dfn[v]){Tarjan(v, u);
low[u]=min(low[u], low[v]);if(low[v]> dfn[u]) cut.push_back(make_pair(u, v));}else
low[u]=min(low[u], dfn[v]);}}voidinit(int n){for(int i =1; i <= n; i ++) e[i].clear(), dfn[i]=0;
cut.clear();}intmain(){int n, m;scanf("%d %d",&n,&m);init(n);for(int i =1, u, v; i <= m; i ++){scanf("%d %d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);}for(int i =1; i <= n; i ++)if(! dfn[i])Tarjan(i,0);for(auto x : cut)printf("%d %d\n", x.first, x.second);return0;}
同时求割点、割边代码
#include<iostream>#include<stdio.h>#include<string.h>#include<math.h>#include<algorithm>#include<string>#include<queue>#include<map>#include<unordered_map>#include<bitset>#include<vector>#include<stack>voidfre(){system("clear"),freopen("A.txt","r",stdin);freopen("Ans.txt","w",stdout);}voidFre(){system("clear"),freopen("A.txt","r",stdin);}#define ios ios::sync_with_stdio(false)#define Pi acos(-1)#define pb push_back#define fi first#define se second#define ll long long#define ull unsigned long long#define db double#define Pir pair<int, int>#define m_p make_pair#define INF 0x3f3f3f3f#define esp 1e-7#define mod (ll)(1e9 + 7)#define for_(i, s, e) for(int i = (ll)(s); i <= (ll)(e); i ++)#define rep_(i, e, s) for(int i = (ll)(e); i >= (ll)(s); i --)#define sc scanf#define pr printf#define sd(a) scanf("%d", &a)#define ss(a) scanf("%s", a)
using namespace std;constint mxn =1e5+10;
vector<int> e[mxn];int low[mxn], dnf[mxn], idx;int dot[mxn];//存储割点int f[mxn];
map<Pir,int> edge;//存储割边voidTarjan(int u,int p,int root){int child =0;
low[u]= dnf[u]=++ idx;for_(i,0, e[u].size()-1){int v = e[u][i];if(v == p)continue;if(! dnf[v]){Tarjan(v, u, root);
low[u]=min(low[u], low[v]);if(u == root) child ++;elseif(low[v]>= dnf[u])
dot[u]=1;if(low[v]> dnf[u]){int x =min(u, v);int y =max(u, v);
edge[m_p(x, y)]=1;}}else low[u]=min(low[u], dnf[v]);}if(u == root && child >=2) dot[root]=1;}voidinit(int n){
idx =0;for_(i,1, n) e[i].clear(), dnf[i]= dot[i]=0;
edge.clear();}intmain(){fre();int n, m;while(~sc("%d %d",&n,&m)){int u, v;for_(i,1, m){sc("%d %d",&u,&v);
e[u].pb(v);
e[v].pb(u);}for_(i,1, n)if(! dnf[i])Tarjan(i,0, i);for(auto[x, y]: edge){
cout << x.fi <<" "<< x.se << endl;}for_(i,1, n)if(dot[i]) cout << i <<" ";}return0;}