连通性问题

求割点

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=2e4+10;
ll n,m,dfn[N],low[N],tot,root;
bool cut[N];
vector<ll> G[N];
void tarjan(ll u){
	dfn[u]=low[u]=++tot;
	ll flag=0;
	for(auto v:G[u]){
		if(!dfn[v]){
			tarjan(v),low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u]){
				flag++;
				if(u!=root||flag>1)cut[u]=true;
			}
		}else low[u]=min(low[u],dfn[v]);
	}
}
int main(){
	cin >> n >> m;
	for(ll i=1;i<=m;i++){
		ll u,v;
		cin >> u >> v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	for(ll i=1;i<=n;i++)if(!dfn[i])root=i,tarjan(i);
	vector<ll> ans;
	for(ll i=1;i<=n;i++)if(cut[i])ans.push_back(i);
	cout << ans.size() << endl;
	for(auto i:ans)cout << i << ' ';
	return 0;
}

求割边

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=150+10,M=5000+10;
vector<ll> G[N],edges;
bool bridge[M*2];
ll n,m,dfn[N],low[N],tot;
void tarjan(ll u,ll in_edge){
	dfn[u]=low[u]=++tot;
	for(auto e:G[u]){
		ll v=edges[e];
		if(!dfn[v]){
			tarjan(v,e),low[u]=min(low[u],low[v]);
			if(low[v]>dfn[u])bridge[e]=bridge[e^1]=true;
		}else if(e!=(in_edge^1))low[u]=min(low[u],dfn[v]);
	}
}
int main(){
	cin >> n >> m;
	for(ll i=1;i<=m;i++){
		ll u,v;
		cin >> u >> v;
		edges.push_back(v);
		edges.push_back(u);
		G[u].push_back(edges.size()-2);
		G[v].push_back(edges.size()-1);
	}
	for(ll i=1;i<=n;i++)if(!dfn[i])tarjan(i,1e18);
	vector<pair<ll,ll> > ans;
	for(ll i=0;i<edges.size();i+=2)
		if(bridge[i])
			ans.push_back(make_pair(edges[i],edges[i^1]));
	for(auto &i:ans)if(i.first>i.second)swap(i.first,i.second);
	sort(ans.begin(),ans.end());
	for(auto i:ans)cout << i.first << ' ' << i.second << endl;
	return 0;
}

同时求出割点和割边

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=5e5+10,M=2e6+10;
ll n,m,tot,root,dfn[N],low[N];
bool bridge[M*2],cut[N];
vector<ll> G[N],edges;
void tarjan(ll u,ll in_edge){
	dfn[u]=low[u]=++tot;
	ll flag=0;
	for(auto e:G[u]){
		ll v=edges[e];
		if(!dfn[v]){
			tarjan(v,e),low[u]=min(low[u],low[v]);
			if(low[v]>dfn[u])bridge[e]=bridge[e^1]=true;
			if(low[v]>=dfn[u])if(u!=root||++flag>1)cut[u]=true;
		}else if(e!=(in_edge^1))low[u]=min(low[u],dfn[v]);
	}
}
int main(){
	cin >> n >> m;
	for(ll i=1;i<=m;i++){
		ll u,v;
		cin >> u >> v;
		edges.push_back(v);
		edges.push_back(u);
		G[u].push_back(edges.size()-2);
		G[v].push_back(edges.size()-1);
	}
	for(ll i=1;i<=n;i++)if(!dfn[i])root=i,tarjan(i,1e18);
	return 0;
}

求边双连通分量(e-DCC)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=5e5+10,M=2e6+10;
ll n,m,tot,dfn[N],low[N],dcc,c[N];
bool bridge[M*2];
vector<ll> G[N],edges;
vector<ll> ans[N];
void tarjan(ll u,ll in_edge){
	dfn[u]=low[u]=++tot;
	for(auto e:G[u]){
		ll v=edges[e];
		if(!dfn[v]){
			tarjan(v,e),low[u]=min(low[u],low[v]);
			if(low[v]>dfn[u])bridge[e]=bridge[e^1]=true;
		}else if(e!=(in_edge^1))low[u]=min(low[u],dfn[v]);
	}
}
void dfs(ll u){
	c[u]=dcc;
	for(auto e:G[u]){
		ll v=edges[e];
		if(c[v]||bridge[e])continue;
		dfs(v);
	}
}
int main(){
	cin >> n >> m;
	for(ll i=1;i<=m;i++){
		ll u,v;
		cin >> u >> v;
		edges.push_back(v);
		edges.push_back(u);
		G[u].push_back(edges.size()-2);
		G[v].push_back(edges.size()-1);
	}
	for(ll i=1;i<=n;i++)if(!dfn[i])tarjan(i,1e18);
	for(ll i=1;i<=n;i++)if(!c[i])++dcc,dfs(i);
	for(ll i=1;i<=n;i++)ans[c[i]].push_back(i);
	cout << dcc << endl;
	for(ll i=1;i<=dcc;i++){
		cout << ans[i].size() << ' ';
		for(auto j:ans[i])cout << j << ' ';
		cout << endl;
	}
	return 0;
}

求点双连通分量(v-DCC)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=5e5+10;
ll n,m,dfn[N],low[N],tot,root,cnt,sz[N];
bool cut[N];
vector<ll> G[N],dcc[N];
stack<ll> sta;
void tarjan(ll u){
	dfn[u]=low[u]=++tot;
	sta.push(u);
	if(u==root&&sz[u]==0){
		dcc[++cnt].push_back(u);
		return;
	}
	ll flag=0;
	for(auto v:G[u]){
		if(!dfn[v]){
			tarjan(v),low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u]){
				if(u!=root||++flag>1)cut[u]=true;
				cnt++;
				ll x;
				do{
					x=sta.top();
					sta.pop();
					dcc[cnt].push_back(x);
				}while(x!=v);
				dcc[cnt].push_back(u);
			}
		}else low[u]=min(low[u],dfn[v]);
	}
}
int main(){
	cin >> n >> m;
	for(ll i=1;i<=m;i++){
		ll u,v;
		cin >> u >> v;
		G[u].push_back(v);
		G[v].push_back(u);
		if(u!=v)sz[u]++,sz[v]++;
	}
	for(ll i=1;i<=n;i++)if(!dfn[i])root=i,tarjan(i);
	cout << cnt << endl;
	for(ll i=1;i<=cnt;i++){
		cout << dcc[i].size() << ' ';
		sort(dcc[i].begin(),dcc[i].end());
		for(auto j:dcc[i]){
			cout << j << ' ';
		}
		cout << endl;
	}
	return 0;
}
posted @ 2024-01-24 13:28  Alric  阅读(3)  评论(0编辑  收藏  举报