WA40pts求调
查看原帖
WA40pts求调
803885
_8008008楼主2024/10/19 11:55

缩点+记忆化搜索

#include<iostream>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;
const int maxn=50005;
vector<int>e[maxn];
vector<int>g[maxn];
int scc[maxn],val[maxn],tot;
//scc[i]节点i所在的scc
//val[i]第i个scc的价值 
int n,m,cnt;
int w[maxn],low[maxn],dfn[maxn];
stack<int>st;
bool inst[maxn],vis[maxn];
int f[maxn];
void tarjan(int u){
	low[u]=dfn[u]=++cnt;
	st.push(u);inst[u]=true;
	for(int i=0;i<e[u].size();i++){
		int v=e[u][i];
		if(dfn[v]==0){
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}else if(inst[v]){
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(low[u]!=dfn[u])return;
	++tot;
	while(st.top()!=u){
		scc[st.top()]=tot;
		val[tot]+=w[st.top()];
		st.pop();
	}
	scc[u]=tot,val[tot]+=w[u];
	inst[u]=false;st.pop();
}
int dp(int u){
	if(f[u]!=-1)return f[u];
	int ans=0;vis[u]=true;
	for(int i=0;i<g[u].size();i++){
		int v=g[u][i];
		if(vis[v])continue;
		ans=max(ans,dp(v));
	}
	f[u]=ans+val[u];
	vis[u]=false;
	return f[u];
}
int main(){
//	freopen("P3387_1.in","r",stdin);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&w[i]);
	}
	for(int i=1;i<=m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		e[u].push_back(v);
	}
	for(int i=1;i<=n;i++){
		if(dfn[i]==0)tarjan(i);
	}
	for(int i=1;i<=n;i++){
		for(int j=0;j<e[i].size();j++){
			int v=e[i][j];
			if(scc[i]==scc[v])continue;
			g[scc[i]].push_back(scc[v]);
		}
	}
	for(int i=1;i<=tot;i++){
		f[i]=-1;
	}
	int ans=0;
	for(int i=1;i<=tot;i++){
		ans=max(ans,dp(i));
	}
	printf("%d",ans);
	return 0;
}
2024/10/19 11:55
加载中...