zoukankan      html  css  js  c++  java
  • 抢掠计划

    [题目链接](https://www.luogu.com.cn/problem/P3627)

    思路

    路可以重复走但是钱不能重复拿,对于一个强连通分量里的点我们肯定把钱都拿光,tarjan缩点

    ans维护从s点出发到每个点最多能拿到多少钱,vis维护每个点能否访问到

    然而直接dfs会t,考虑到每次判断从当前点到儿子ans[u]+ww[v]>ans[v]?访问儿子:不访问

    不妨所有儿子中先更新较大的儿子

    玄学堆优化+bfs

    代码

    dfs:

    #include<bits/stdc++.h>
    using namespace std;
    int uu[600100],vv[600000],cnt=0,head[600000],dfn[600000],low[600000],t=0,in[600000],sta[600000],stac=0,
    color[600000],colornum=0,ww[600000],w[600000],ans[600000],vis[600000];
    struct node{
    	int to,nxt;
    }road[600000];
    void build(int u,int v)
    {
    	road[++cnt].to=v;
    	road[cnt].nxt=head[u];
    	head[u]=cnt;
    }
    void tarjan(int u)
    {
    	dfn[u]=low[u]=++t;
    	in[u]=1;sta[++stac]=u;
    	for(int i=head[u];i;i=road[i].nxt)
    	{
    		int v=road[i].to;
    		if(!dfn[v])
    		{
    			tarjan(v);
    			low[u]=min(low[u],low[v]);
    		}
    		else if(in[v]) low[u]=min(low[u],dfn[v]);
    	}
    	if(dfn[u]==low[u])
    	{
    		color[u]=++colornum;
    		in[u]=0;
    		ww[colornum]+=w[u];
    		while(sta[stac]!=u)
    		{
    			color[sta[stac]]=colornum;
    			in[sta[stac]]=0;
    			ww[colornum]+=w[sta[stac]];
    			stac--;
    		}
    		stac--;
    	}
    }
    void dfs(int u)
    {
    	vis[u]=1;
    	for(int i=head[u];i;i=road[i].nxt)
    	{
    		int v=road[i].to;
    		if(ans[u]+ww[v]>ans[v]) 
    		{
    			ans[v]=ans[u]+ww[v];
    			dfs(v);
    		}
    	}
    }
    int main()
    {
    	int n,m;
    	cin>>n>>m;
    	for(int i=1;i<=m;i++)
    	{
    		cin>>uu[i]>>vv[i];
    		build(uu[i],vv[i]);
    	}
    	for(int i=1;i<=n;i++) cin>>w[i];
    	for(int i=1;i<=n;i++)
    	{
    		if(!dfn[i]) tarjan(i);
    	}
    	int s,p;
    	cin>>s>>p;
    	memset(head,0,sizeof(head));
    	cnt=0;
    	for(int i=1;i<=m;i++)
    	{
    		if(color[uu[i]]!=color[vv[i]])
    		{
    			build(color[uu[i]],color[vv[i]]);
    		}
    	}
    	memset(ans,0,sizeof(ans));
    	memset(vis,0,sizeof(vis));
    	ans[color[s]]=ww[color[s]];//QAQ带上color 
    	vis[color[s]]=1;
    	for(int i=head[color[s]];i;i=road[i].nxt)
    	{
    		int v=road[i].to;
    		if(ans[color[s]]+ww[v]>ans[v]) 
    		{
    			ans[v]=ans[color[s]]+ww[v];//是ww不是w呀 
    			dfs(v);
    		}
    	}
    	int maxn=-1;
    	for(int i=1;i<=p;i++)
    	{
    		int x;
    		cin>>x;
    		if(vis[color[x]]) maxn=max(maxn,ans[color[x]]);//QAQ带上color 
    	}
    	cout<<maxn;
    	return 0;
    }
    

    bfs

    #include<bits/stdc++.h>
    using namespace std;
    int uu[600100],vv[600000],cnt=0,head[600000],dfn[600000],low[600000],t=0,in[600000],sta[600000],stac=0,
    color[600000],colornum=0,ww[600000],w[600000],ans[600000],vis[600000];
    priority_queue< pair<int,int> > q1;
    priority_queue< pair<int,int> > q2;
    struct node{
    	int to,nxt;
    }road[600000];
    void build(int u,int v)
    {
    	road[++cnt].to=v;
    	road[cnt].nxt=head[u];
    	head[u]=cnt;
    }
    void tarjan(int u)
    {
    	dfn[u]=low[u]=++t;
    	in[u]=1;sta[++stac]=u;
    	for(int i=head[u];i;i=road[i].nxt)
    	{
    		int v=road[i].to;
    		if(!dfn[v])
    		{
    			tarjan(v);
    			low[u]=min(low[u],low[v]);
    		}
    		else if(in[v]) low[u]=min(low[u],dfn[v]);
    	}
    	if(dfn[u]==low[u])
    	{
    		color[u]=++colornum;
    		in[u]=0;
    		ww[colornum]+=w[u];
    		while(sta[stac]!=u)
    		{
    			color[sta[stac]]=colornum;
    			in[sta[stac]]=0;
    			ww[colornum]+=w[sta[stac]];
    			stac--;
    		}
    		stac--;
    	}
    }
    void bfs()
    {
    	while(!q2.empty())
    	{
    		int u=q2.top().first;q2.pop();
    		for(int i=head[u];i;i=road[i].nxt)
    		{
    			int v=road[i].to;
    			vis[v]=1;
    			if(ans[u]+ww[v]>ans[v]) 
    			{
    				ans[v]=ans[u]+ww[v];
    				q2.push(make_pair(v,ans[v]));
    			}
    		}
    	}
    }
    int main()
    {
    	int n,m;
    	cin>>n>>m;
    	for(int i=1;i<=m;i++)
    	{
    		cin>>uu[i]>>vv[i];
    		build(uu[i],vv[i]);
    	}
    	for(int i=1;i<=n;i++) cin>>w[i];
    	for(int i=1;i<=n;i++)
    	{
    		if(!dfn[i]) tarjan(i);
    	}
    	int s,p;
    	cin>>s>>p;
    	memset(head,0,sizeof(head));
    	cnt=0;
    	for(int i=1;i<=m;i++)
    	{
    		if(color[uu[i]]!=color[vv[i]])
    		{
    			build(color[uu[i]],color[vv[i]]);
    		}
    	}
    	memset(ans,0,sizeof(ans));
    	memset(vis,0,sizeof(vis));
    	ans[color[s]]=ww[color[s]];//QAQ带上color 是ww不是w呀
    	vis[color[s]]=1;
    	for(int i=head[color[s]];i;i=road[i].nxt)
    	{
    		int v=road[i].to;
    		if(ans[color[s]]+ww[v]>ans[v]) 
    		{
    			ans[v]=ans[color[s]]+ww[v];
    			q1.push(make_pair(v,ans[v]));
    		}
    	}
    	while(!q1.empty())
    	{
    		int u=q1.top().first;
    		q1.pop();
    		vis[u]=1;
    		q2.push(make_pair(u,ans[u]));//QAQ
    		bfs();
    	}
    	int maxn=-1;
    	for(int i=1;i<=p;i++)
    	{
    		int x;
    		cin>>x;
    		if(vis[color[x]]) maxn=max(maxn,ans[color[x]]);//QAQ带上color 
    	}
    	cout<<maxn;
    	return 0;
    }
    
  • 相关阅读:
    专家视角 | 小荷的 Oracle Database 18c 新特性快速一瞥
    java.lang.ClassCastException: com.xx.User cannot be cast to com.xx.User
    上传单个文件
    极速体验:Oracle 18c 下载和Scalable Sequence新特性
    开工大吉:Oracle 18c已经发布及新特性介绍
    CentOS7编译安装NodeJS
    .NET 同步与异步之锁(ReaderWriterLockSlim)(八)
    .NET 同步与异步之锁(ReaderWriterLockSlim)(八)
    .NET 同步与异步之锁(ReaderWriterLockSlim)(八)
    .NET 同步与异步之锁(ReaderWriterLockSlim)(八)
  • 原文地址:https://www.cnblogs.com/qwq-/p/13637918.html
Copyright © 2011-2022 走看看