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(){IOScin>>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++){//tarjanif(!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(){IOSsolve();return 0;
}