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;
}

浙公网安备 33010602011771号