首页 > 其他分享 >Atm/抢掠计划——题解

Atm/抢掠计划——题解

时间:2024-02-21 21:13:52浏览次数:28  
标签:tarjan 抢掠 temp int 题解 Atm vis spfa low

题目描述

image

样例

6 7
1 2
2 3
3 5
2 4
4 1
2 6
6 5
10
12
8
16
1 5
1 4
4
3
5
6
47

解析

题目明显是最长路,可以用spfa求最长路,但数据范围5e5明显不允许,所以我们可以用tarjan优化一下,然后这就变成了一道

tarjan板子题,先用tarjan缩点,点权为几个点之和,把所有点再存到一个数组中,再按之前建图关系,把不在一个块的点连边

再跑一遍spfa就可以了

solution

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+5;
const int INF=0x7f7f7f7f;
int tot,head[MAXN],nxt[MAXN<<1],to[MAXN<<1],pre[MAXN],vis[MAXN],low[MAXN];
int n,m,s,st,t,h,r,c,d,cnt,now,ans,w,sum,num,val[MAXN],id[MAXN],out[MAXN];
int a[MAXN],b[MAXN],bill[MAXN],x[MAXN],y[MAXN],dis[MAXN];
void add(int x,int y)
{
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}
stack<int>p;
void tarjan(int u)
{
    pre[u]=low[u]=++cnt;
    p.push(u);
    vis[u]=1;
    for(int i=head[u];i;i=nxt[i])
    {
        int y=to[i];
        if(!pre[y])
        {
            tarjan(y);
            low[u]=min(low[u],low[y]);
        }
        else if(vis[y])
        {
            low[u]=min(low[u],pre[y]);
        }
    }
    if(low[u]==pre[u])
    {
        num++;
        int temp=-1;
        while(temp!=u){
            temp=p.top();
            p.pop();
            vis[temp]=0;
            id[temp]=num;//把所有点再存到这个数组中
            val[num]+=a[temp];//块点权为所有包含点之和
            if(b[temp]) bill[num]=1;//如果缩进的点有酒吧,则本块又酒吧
        }
    }
}
queue<int>q;
void spfa()//spfa求最长路
{ 
	memset(dis,-0x7f7f7f7f,sizeof(dis));
	q.push(id[st]);
    dis[id[st]]=val[id[st]];//先加上本点点权,以后跑的边的边权即为边通向点的点权
	//vis[st]=true;
	while(!q.empty())
	{
		s=q.front();
		q.pop();
		vis[s]=false;
		for(int i=head[s];i;i=nxt[i])
		{
			int y=to[i];
			if(dis[y]<dis[s]+val[y])//保证权值为正,不用判负环
			{
				dis[y]=dis[s]+val[y];
				if(!vis[y])
				{
					q.push(y);
					vis[y]=true;
				}
			}
		}
	}
    ans=-INF;
    for(int i=1;i<=num;i++)
    {
        if(bill[i]) ans=max(ans,dis[i]);//只看有酒吧的
    }
    printf("%d",ans);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&r,&c);
        x[i]=r,y[i]=c;//记录链接点
        add(r,c);
    }
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    scanf("%d%d",&st,&t);
    for(int i=1;i<=t;i++)
    {
        scanf("%d",&d);
        b[d]=1;//有酒吧
    }
    for(int i=1;i<=n;i++)if(!pre[i]) tarjan(i);
    memset(head,0,sizeof(head));//缩点后重建图,初始化
    tot=0;
    for(int i=1;i<=m;i++) if(id[x[i]]!=id[y[i]]) add(id[x[i]],id[y[i]]);//原本连通的点是否在同一个块中,不在的建边
    spfa();
    return 0;
}

标签:tarjan,抢掠,temp,int,题解,Atm,vis,spfa,low
From: https://www.cnblogs.com/dfxjlsx/p/18026209

相关文章

  • 洛谷P4447题解
    md这篇反正不交题解的,随便写,不管它格式题意简化下,给你N个数,求出连续值分组人数最小的那组的人数最大值。这个题目还挺经典的,原本23年8月份过了到现在来又不会了(划掉,bushi对于这种,很容易想到的是输入,之后排序,然后分组这种模板就不多说了,就在我24年2月份重温这道题再打一遍代码......
  • RxJS中高阶映射操作符的全面讲解:switchMap, mergeMap, concatMap (and exhaustMap)
    原文链接:https://blog.angular-university.io/rxjs-higher-order-mapping/有一些在日常开发中常用的RxJS的操作符是高阶操作符:switchMap,mergeMap,concatMap,以及exhaustMap。举个例子,程序中大多数的网络请求都是通过以上某个操作符来完成的,所以为了能够写出几乎所有反应式编程,必须......
  • 1 c++算法题解析-两个数之和
    //给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。//你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。//你可以按任意顺序返回答案。//示例1:////输入:nums=[2,7,......
  • ARC111B Reversible Cards 题解 (套路题)
    考虑将\(a_i,b_i\)之间连边,发现题目可以被转化为给定一个图,要求对于每条边将其一个顶点染色,问最多能将多少个点染色。于是我们对于每个连通块分开来考虑。对于一个连通块,注意到我们不能将每个顶点染色当且仅当这个连通块是树,且此时可以染色的定点数量为连通块大小减一,如下:如......
  • blocks——题解
    题目描述解析对于这道题,他要求大于k的数进行操作,所以直接让每个数减k,然后用前缀和维护一下与0比较就可以了,因为一段区间和的平均值大于k的话,那么这就是一个合法区间,即为操作后的这个区间和大于0,我们可以用一个单调递减栈去维护,先把比0小的推入栈中,因为要求最大区间,所以边界......
  • 良好的感觉——题解
    题目描述分析题目意思就是找子区间的和乘区间最小值的最小值;1.纯暴力。。。肯定TLE.2.枚举最小值,找两边第一个比它小的,求区间和。(肯定第二种)。。。实现纯循环的话肯定不行,这时候需要一点小优化——单调栈;既然枚举最小值的话,复杂度只要O(n),可以用前缀和求区间和,接下来就是......
  • P4141 消失之物题解(写给每一位与我一样的新手玩家)
    消失之物传送门:P4141消失之物-洛谷|计算机科学教育新生态(luogu.com.cn)思路暴力稳了但是hacktle了这时候我们要想办法优化这是一个回退背包问题首先第一步,我们把正常的背包(n间物体)求出来,然后就是板子,求出填满当中体积有多少种方法第二步就是回退,回退的关键问题......
  • luogu5021题解
    形式化题意:在一棵树上找\(m\)条没有重复边的路径,使得最短的路径最大,求这个最短路径的最大值。看到这个最大值就想二分答案。\(1\lem\len-1\),我们可以将长度的下限为最短的那条边,此时所有边都是符合要求的路径。长度的上限为所有路径的长度除以\(m\),向下取整。我们在判断......
  • 2024年2月20号题解
    P5594【XR-4】模拟赛解题思路重点是怎么判断是不是同一套模拟题用一个数组来标记是不是同一套题代码实现#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<time.h>#include<stdbool.h>#defi......
  • B3893 [NICA #3] 一键三连 题解
    本文同步发布于洛谷博客水题啊,我发现chen_zhe上传的水题这么多呢?难道kkksc03把水题都交给他上传了?题意简述输入两个整数\(x\)和\(y\),输出\(x+y\times2\)。我能直接上代码吗好的,让我们通过做题认识一下相关的知识点:YF001int类型与输入输出YF002数与数之间的运......