【图论】tarjan求割点和桥(无向双联通)

参考:https://blog.csdn.net/wtyvhreal/article/details/43530613
因为我是用邻接表写的,所以时间复杂度:O(n+m);
求割点模板:

#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=2e5+10;
vector<ll> edge[maxn];
ll root;
ll dfn[maxn],low[maxn],tot,n,m,ans=-1,vis[maxn],flag[maxn];
stack<ll> s;
void tarjan(ll x,ll father){
	ll child=0;
	low[x]=dfn[x]=++tot;
	s.push(x);vis[x]=1;
	for(ll i=0;i<edge[x].size();i++){
		ll v=edge[x][i];
		if(!dfn[v]){
			child++;
			tarjan(v,x);
			low[x]=min(low[x],low[v]);
			if(x!=root&&low[v]>=dfn[x]) flag[x]=1;
			if(x==root&&child==2) flag[x]=1;
		}else if(v!=father){
			low[x]=min(low[x],dfn[v]);
		}
	}
}
int main(){
	cin>>n>>m;
	for(ll i=1;i<=m;i++){
		ll u,v;cin>>u>>v;
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	root=1;
	for(ll i=1;i<=n;i++){
		if(!dfn[i]) tarjan(i,root);
	}
	cout<<endl;
	for(ll i=1;i<=n;i++){
		if(flag[i]==1) cout<<i<<" ";
	}
}
/*
7 7
1 2
2 3
3 4
2 5
4 5
5 6
5 7

*/

求桥模板:

#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=2e5+10;
vector<ll> edge[maxn];
ll root;
ll dfn[maxn],low[maxn],tot,n,m,ans=-1,vis[maxn],flag[maxn];
stack<ll> s;
void tarjan(ll x,ll father){
	low[x]=dfn[x]=++tot;
	s.push(x);vis[x]=1;
	for(ll i=0;i<edge[x].size();i++){
		ll v=edge[x][i];
		if(!dfn[v]){
			tarjan(v,x);
			low[x]=min(low[x],low[v]);
			if(low[v]>dfn[x]) printf("%d-%d\n",x,v);
		}else if(v!=father){
			low[x]=min(low[x],dfn[v]);
		}
	}
}
int main(){
	cin>>n>>m;
	for(ll i=1;i<=m;i++){
		ll u,v;cin>>u>>v;
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	root=1;
	for(ll i=1;i<=n;i++){
		if(!dfn[i]) tarjan(i,root);
	}
}
/*
7 7
1 2
2 3
3 4
2 5
4 5
5 6
5 7

*/

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

发布了90 篇原创文章 · 获赞 6 · 访问量 5005

猜你喜欢

转载自blog.csdn.net/Rainfoo/article/details/104518498
今日推荐