P3387求调
查看原帖
P3387求调
1086931
bishenke_2008楼主2024/10/25 21:39

本人纯唐代码,初学tarjan求调,不胜感激!
评测记录

#include<bits/stdc++.h>
using namespace std;
#define next Next
const int N=500005;

int n,m;
int a[N];
int cnt=1;
int head[N];
int next[N],ver[N];
int in[N];
int num=0;
int top=0;
stack<int> s;
bool ins[N];
int res=0;
int dfn[N],low[N];
bool c[N];
int scc[N];

void add(int u,int v){
	next[cnt]=head[u];
	ver[cnt]=v;
	head[u]=cnt++;
}

void tarjan(int x){
	dfn[x]=low[x]=++num;
	s.push(x);
	ins[x]=true;
	for(int i=head[x];i;i=next[i]){
		int y=ver[i];
		if(!dfn[y]){
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}
		else if(ins[y])
			low[x]=min(low[x],dfn[y]);
	}
	if(dfn[x]==low[x]){
		res++;
		int z;
		while(s.top()!=x){
			z=s.top();
			s.pop();
			ins[z]=false;
			c[z]=res;
			scc[res]+=a[z];
		}
		s.pop();
		ins[x]=false;
		c[x]=res;
		scc[res]+=a[x];
	}
}

int topo(){
	int dp[N];
	queue<int> q;
	for(int i=1;i<=n;i++)
		if(!in[i]){
			dp[i]=scc[i];
			q.push(i);
		}
	while(!q.empty()){
		int x=q.front();
		q.pop();
		for(int i=head[x];i;i=next[i]){
			int y=ver[i];
			dp[y]=max(dp[y],dp[x]+scc[y]);
			in[y]--;
			if(!in[y])
				q.push(y);
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++)
		ans=max(ans,dp[i]);
	return ans;
}

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=m;i++){
		int u,v;
		cin>>u>>v;
		if(u==v) continue;
		add(u,v);
	}
	
	for(int i=1;i<=n;i++)
		if(!dfn[i]){
			top=0;
			tarjan(i);
		}
	
	cnt=1;
	memset(head,0,sizeof(head));
	memset(next,0,sizeof(next));
	memset(ver,0,sizeof(ver));
	
	for(int x=1;x<=n;x++)
		for(int i=head[x];i;i=next[i]){
			int y=ver[i];
			if(c[x]==c[y]) continue;
			add(c[x],c[y]);
		}
	
	cout<<topo();
	return 0;
}
2024/10/25 21:39
加载中...