Tarjan——强连通分量

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

posted @ 2025-11-26 13:54  10mbps_十兆網路  阅读(0)  评论(0)    收藏  举报