Tarjan + Topo 样例没过 求教
查看原帖
Tarjan + Topo 样例没过 求教
205782
R浩轩泽Anmicius楼主2020/8/6 12:14

继承着Tarjan缩点后可以在DAG上乱搞求解的优良传统,喜提123行代码+样例WA

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
const int N=200010;
const int E=500010;
#define re register int
int n,m,st,p,val[N],num,head[N],dfn[N],low[N],sta[N],visn,stan,in[N],sta_val[N],sta_max[N],ans;
vector<int>sta_node[N];
//in 每个强连通分量的入度   sta_node 每个强连通分量内都有哪些节点   sta_max 到达每个强连通分量时得到最多的钱数 
bool bar[N],sta_bar[N]; 
stack<int>s;
queue<int>q;
struct Edge{
	int to;
	int next;
}edge[E];
inline void AddEdge(int x,int y)
{
	edge[++num].to=y;
	edge[num].next=head[x];
	head[x]=num;
}
void Tarjan(int u)
{
	dfn[u]=low[u]=++visn;
	s.push(u);
	for(re i=head[u];i;i=edge[i].next)
	{
		int v=edge[i].to;
		if(!dfn[v])
		{
			Tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(!sta[v])
		low[u]=min(low[u],low[v]);//此处可修改 
	}
	if(dfn[u]==low[u])
	{
		sta[u]=++stan;
		sta_node[stan].push_back(u);
		sta_val[stan]+=val[u];
		if(bar[u])sta_bar[stan]=true;
		while(s.top()!=u)
		{
			sta[s.top()]=stan;
			sta_node[stan].push_back(s.top());
			sta_val[stan]+=val[s.top()]; 
			if(bar[s.top()])sta_bar[stan]=true;
			s.pop();
		}
		s.pop();
	}
}
inline void Topo(int starts)
{
	q.push(starts);
	while(!q.empty())
	{
		int fro=q.front();//fro是强连通分量 
		q.pop();
		for(re k=0;k<sta_node[fro].size();++k)//枚举点 
		{
			for(re i=head[k];i;i=edge[i].next)//枚举边 
			{
				int to=edge[i].to;//是点 
				if(sta[k]!=sta[to])
				{
					sta_max[sta[to]]=max(sta_max[sta[to]],sta_max[fro]+sta_val[sta[to]]);
					if(!(--in[sta[to]]))q.push(sta[to]); 
				}
			}
		}
	}
}
inline void starts()
{
	memset(head,0,sizeof(head));
	memset(dfn,0,sizeof(dfn));
	memset(low,0,sizeof(low));
	memset(sta,0,sizeof(sta));
	memset(sta_val,0,sizeof(sta_val));
	memset(sta_max,0,sizeof(sta_max)); 
	memset(bar,false,sizeof(bar));
	memset(sta_bar,false,sizeof(sta_bar));
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m;
	starts();
	for(re i=1;i<=m;++i)
	{
		int x,y;
		cin>>x>>y;
		AddEdge(x,y);
	}
	for(re i=1;i<=n;++i)
	cin>>val[i];
	cin>>st>>p;
	for(re i=1;i<=p;++i)
	{
		int k;
		cin>>k;
		bar[k]=true;
	}
	for(re i=1;i<=n;++i)
	if(!dfn[i])Tarjan(i);
	for(re k=1;k<=n;++k)
	for(re i=head[k];i;i=edge[i].next)
	{
		int to=edge[i].to;
		if(sta[k]!=sta[to])++in[to];
	}
	Topo(sta[st]);
	for(re i=1;i<=stan;++i)
	if(sta_bar[i])ans=max(ans,sta_max[i]);
	cout<<ans;
	return 0;
} 

求解求解

2020/8/6 12:14
加载中...