Tarjan 学习笔记

Tarjan 学习笔记

有向图连通性问题

强联通分量

模板

其实简单,直接模板就行了,上代码:

#include <bits/stdc++.h>

#define int long long

using namespace std;

const int N=1e4+10;
const int M=1e5+10;

int n,m;
vector<int> e[N];
vector<vector<int> > SCC;
bool instack[N];
int dfn[N],low[N],cnt;
stack<int> st;

void readin() {
	cin>>n>>m;
	for(int i=1;i<=m;++i) {
		int u,v;
		cin>>u>>v;
		e[u].push_back(v);
	}
}

void dfs(int now) {
	instack[now]=1;
	st.push(now);
	dfn[now]=low[now]=(++cnt);
	for(auto k:e[now]) {
		if(dfn[k]==0) {
			dfs(k);
			low[now]=min(low[now],low[k]);
		}
		else if(instack[k]) 
			low[now]=min(low[now],dfn[k]);
	}
	if(low[now]==dfn[now]) {
		vector<int> C;
		while(st.top()!=now) {
			C.push_back(st.top());
			instack[st.top()]=0;
			st.pop();
		}
		C.push_back(st.top());
		instack[st.top()]=0;
		st.pop();
		sort(C.begin(),C.end());
		SCC.push_back(C);
	}
}

void Tarjan() {
	for(int i=1;i<=n;++i) {
		if(dfn[i]==0) 
			dfs(i);
	}
}

void output() {
	sort(SCC.begin(),SCC.end());
	cout<<SCC.size()<<"\n";
	for(auto C:SCC) {
		for(auto k:C) {
			cout<<k<<" ";
		}
		cout<<"\n";
	}
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	readin();
	Tarjan();
	output();
	return 0;
}

【模板】缩点

注意 \(DP\) 要么在反图上跑要么把拓扑序倒过来。

#include <bits/stdc++.h>

#define int long long 

using namespace std;

const int N=1e4+10;
const int M=1e5+10;

int n,m;
vector<int> e[N];
vector<int> g[N];
int sz[N];
int idx;//素质
int low[N];
int dfn[N];
int cnt;//素质
stack<int> st;
bool instack[N];
int belong[N];
int ux[M],vx[M];
int in[N];//素质
vector<int> topo;//素质
int f[N];
int w[N];

void dfs(int now) {
	st.push(now);
	instack[now]=1;
	low[now]=dfn[now]=(++cnt);
	for(auto k:e[now]) {
		if(dfn[k]==0) {
			dfs(k);
			low[now]=min(low[now],low[k]);
		}
		else{
			if(instack[k]) {
				low[now]=min(low[now],dfn[k]);
			}
		}
	}
	if(dfn[now]==low[now]) {
		++idx;
		while(!st.empty()&&st.top()!=now) {
			sz[idx]+=w[st.top()];
			belong[st.top()]=idx;
			instack[st.top()]=0;
			st.pop();
		}
		sz[idx]+=w[st.top()];
		belong[now]=idx;
		instack[now]=0;
		st.pop();
	}
}//素质素质素质

void build_graph() {
	//素质
	for(int i=1;i<=m;++i) {
		if(belong[ux[i]]==belong[vx[i]]) continue;
		g[belong[ux[i]]].push_back(belong[vx[i]]);
		in[belong[vx[i]]]++;
	}
}

void topo_sort() {
	//素质素质
	queue<int> q;
	for(int i=1;i<=idx;++i) {
		if(in[i]==0) {
			q.push(i);
		}
	}
	while(!q.empty()) {
		topo.push_back(q.front());
		int x=q.front();
		q.pop();
		for(auto k:g[x]) {
			in[k]--;
			if(in[k]==0) {
				q.push(k);
			}
		}
	}
}

void dp() {
	//素质素质
	reverse(topo.begin(),topo.end());
	for(auto k:topo) {
		int maxx=0;
		for(auto x:g[k]) {
			maxx=max(maxx,f[x]);
		}
		f[k]=sz[k]+maxx;
	}
}

int getans() {
	int res=numeric_limits<int>::min();
	for(auto k:topo) {
		res=max(res,f[k]);
	}
	return res;
}

void readin() {
	cin>>n>>m;
	for(int i=1;i<=n;++i) {
		cin>>w[i];
	}
	for(int i=1;i<=m;++i) {
		cin>>ux[i]>>vx[i];
		e[ux[i]].push_back(vx[i]);
	}
}

void tarjan() {
	for(int i=1;i<=n;++i) {
		if(dfn[i]==0) {
			dfs(i);
		}
	}
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	readin();
	tarjan();
	build_graph();
	topo_sort();
	dp();
	cout<<getans()<<"\n";
	return 0;
}
posted @ 2025-08-21 19:10  guoguo160  阅读(11)  评论(0)    收藏  举报