Tarjan——强连通分量
B3609 [图论与代数结构 701] 强连通分量
#include<bits/stdc++.h>
using namespace std;
//#define int long long
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
const int N=10010;
const int M=200010;
struct Edge{
int to,nex;
}edge[4*M];
int cnt;
int head[N];
void add_edge(int x,int y){
edge[++cnt].to=y;
edge[cnt].nex=head[x];
head[x]=cnt;
return;
}
int n,m;
int dfn[N],low[N],bel[N],scc,sccn[N],tot;
vector<int>sccp[N];
bool instk[N],vis[N];
int stk[N],top;
void tarjan(int u){
vis[u]=1;
dfn[u]=low[u]=++tot;
instk[stk[++top]=u]=1;
for(int pos=head[u];pos;pos=edge[pos].nex){
int v=edge[pos].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[v],low[u]);
}
else if(instk[v]){
low[u]=min(low[u],dfn[v]);//一定是 dfn[v] 因为low[v]有可能还没有更新完毕
}
}
if(low[u]==dfn[u]){
scc++;
int cur;
do{
cur=stk[top--];
bel[cur]=scc;
sccn[scc]++;
sccp[scc].push_back(cur);
instk[cur]=0;
}while(u!=cur);
}
}
int in_num[N],out_num[N];
signed main(){
IOS
cin>>n>>m;
for(int i=1;i<=m;i++){
int in1,in2;
cin>>in1>>in2;
add_edge(in1,in2);
}
for(int i=1;i<=n;i++){
if(!vis[i])tarjan(i);
}
for(int i=1;i<=scc;i++)
sort(sccp[i].begin(),sccp[i].end());
cout<<scc<<endl;
bool visscc[N]={};
for(int i=1;i<=n;i++){
if(!visscc[bel[i]]){
for(int t:sccp[bel[i]])cout<<t<<' ';
cout<<endl;
visscc[bel[i]]=1;
}
}
return 0;
}
P3387 【模板】缩点
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0);cout.tie(0);cin.tie(0);
#define endl '\n'
#define int long long
const int N=1e4+114;
const int M=1e5+114;
struct Edge{
int to,nex;
}edge[M],edge_scc[N];
int head[N],cnt;
void add_edge(int a,int to_b){
edge[++cnt].nex=head[a];
edge[cnt].to=to_b;
head[a]=cnt;
}
int head_scc[N],cnt_scc;
int sccinnum[N];
void add_edge_scc(int a,int to_b){
edge_scc[++cnt_scc].nex=head_scc[a];
edge_scc[cnt_scc].to=to_b;
head_scc[a]=cnt_scc;
}
int val[N];
bool instk[N];
int stk[N],top;
int dfn[N],low[N],tot;
int sccnum,bel[N];
int sccval[N];
void tarjan(int u){
dfn[u]=low[u]=++tot;
instk[stk[++top]=u]=1;
for(int i=head[u];i;i=edge[i].nex){
int v=edge[i].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instk[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
sccnum++;
while(instk[u]){
int topp=stk[top];
bel[topp]=sccnum;
sccval[sccnum]+=val[topp];
instk[topp]=0;
top--;
}
}
return;
}
void solve(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>val[i];
}
for(int i=1;i<=m;i++){
int a,to_b;
cin>>a>>to_b;
add_edge(a,to_b);
}
for(int i=1;i<=n;i++){//tarjan
if(!dfn[i]){
tarjan(i);
}
}
for(int i=1;i<=n;i++){//建立新图
for(int j=head[i];j;j=edge[j].nex){
int to=edge[j].to;
if(bel[i]!=bel[to]){
add_edge_scc(bel[i],bel[to]);
sccinnum[bel[to]]++;
}
}
}
queue<int>que;//拓扑排序
for(int i=1;i<=sccnum;i++){
if(sccinnum[i]==0){
que.push(i);
}
}
int ans[N]={};
bool vis[N]={};
while(!que.empty()){
int pos=que.front();
que.pop();
vis[pos]=1;
ans[pos]+=sccval[pos];
for(int i=head_scc[pos];i;i=edge_scc[i].nex){
int to=edge_scc[i].to;
if(!vis[to]){
ans[to]=max(ans[to],ans[pos]);
sccinnum[to]--;
if(sccinnum[to]==0)que.push(to);
}
}
}
int maxn=0;
for(int i=1;i<=sccnum;i++){
maxn=max(maxn,ans[i]);
}
cout<<maxn<<endl;
}
signed main(){
IOS
solve();
return 0;
}