先来看一下题目描述:

题目描述

Siruseri 城中的道路都是单向的。不同的道路由路口连接。按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机。令人奇怪的是,Siruseri 的酒吧也都设在路口,虽然并不是每个路口都设有酒吧。

Banditji 计划实施 Siruseri 有史以来最惊天动地的 ATM 抢劫。他将从市中心 出发,沿着单向道路行驶,抢劫所有他途径的 ATM 机,最终他将在一个酒吧庆 祝他的胜利。

使用高超的黑客技术,他获知了每个 ATM 机中可以掠取的现金数额。他希 望你帮助他计算从市中心出发最后到达某个酒吧时最多能抢劫的现金总数。他可 以经过同一路口或道路任意多次。但只要他抢劫过某个 ATM 机后,该 ATM 机 里面就不会再有钱了。 例如,假设该城中有 6 个路口,道路的连接情况如下图所示:

市中心在路口 1,由一个入口符号→来标识,那些有酒吧的路口用双圈来表

示。每个 ATM 机中可取的钱数标在了路口的上方。在这个例子中,Banditji 能抢 劫的现金总数为 47,实施的抢劫路线是:1-2-4-1-2-3-5。

输入输出格式

输入格式:

第一行包含两个整数 N、M。N 表示路口的个数,M 表示道路条数。接下来 M 行,每行两个整数,这两个整数都在 1 到 N 之间,第 i+1 行的两个整数表示第 i 条道路的起点和终点的路口编号。接下来 N 行,每行一个整数,按顺序表示每 个路口处的 ATM 机中的钱数。接下来一行包含两个整数 S、P,S 表示市中心的 编号,也就是出发的路口。P 表示酒吧数目。接下来的一行中有 P 个整数,表示 P 个有酒吧的路口的编号。

输出格式:

输出一个整数,表示 Banditji 从市中心开始到某个酒吧结束所能抢劫的最多 的现金总数。

好了,以上是题目描述qwq。

那么现在我们考虑一下用什么方法来做这道题。

首先我们明确一点:这是一个有向有环图。所以我们就应该考虑Tarjan之类的用以处理有向图的方法了。

按照最初的印象,我们好像应该是要跑一次最长路,SPFA完全可以做到这一点。但是我们要知道,他有两个特殊条件:

  1.没有边权,只有点权,也没有消耗。并且我们是要从这个图里面获得最大的点权,也就是说:边可以走好多次,但是点走一次之后就变为了0。

  2.我们最后要回到某一个指定的位置。所以SPFA就十分方便。

所以在经过反复思考后,我们决定用Tarjan解决这个问题。那么为什么呢?

因为Tarjan可以很好地解决关于图的连通性的问题。 由此,我们就可以把一个环缩成一个点。

因为我们知道,一旦我们进入了一个环,由于不计费用,所以我们最佳的方案就是直接跑完这个环。就像样例中的1,2,4一样。

好了接下来讲一下如何实现。

1.首先用Tarjan将所有的环所称一个点。

2.跑一边最长路SPFA。

(好像根本没有什么总结的必要emmmm......)

那么接下来是各段的代码。

#define MAXN 100010
int Yeasion[MAXN];//DFS时搜索的顺序。
int Nein[MAXN];//Nein[i]就是表示在当前i节点能够回到的最大的节点处。
bool flag[MAXN];//是否在栈里面
int belong[MAXN];//表示i节点在Tarjan之后属于什么节点。
int value[MAXN];//表示Tarjan之前的节点的价值
int behind_value[MAXN];//表示Tarjan之后的节点价值
int stack[MAXN],cnt,top,ken;//......
vector<int> line[MAXN];//使用不定长数组代替前向星,好像会简洁一点emmmm.....
void Tarjan(int now)
{//一下是固定不变的Tarjan  qwq Nein[now]=Yeasion[now]=++ken;stack[++top]=now;flag[now]=true;for(int i=0;i<line[now].size();i++){int next=line[now][i];if(!Yeasion[next]){Tarjan(next);if(Nein[next]<Nein[now])Nein[now]=Nein[next];}elseif(flag[next])Nein[now]=min(Yeasion[next],Nein[now]);}if(Nein[now]==Yeasion[now]){cnt++;//这里我们在Tarjan之后新建了一个图,然后我们资金编造了一个顺序。 int pass;//顾名思义,过去的节点嘛... do{pass=stack[top--];//更新pass,进行退栈操作。 belong[pass]=cnt;//表明原图中的pass点属于新图中的cnt节点。 behind_value[cnt]+=value[pass];//更新新图中的cnt的节点大小 flag[pass]=false;//退栈..... }while(pass!=now);}return ;
}

然后我们跑一边SPFA就可以了。下面上全部代码。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#define MAXN 100001
using namespace std;int n,m,s,p;//SPFA用
int dist[561100];
queue<int>q;
bool inque[501000];//Tarjan用
int Yeasion[MAXN];//DFS时搜索的顺序。
int Nein[MAXN];//Nein[i]就是表示在当前i节点能够回到的最大的节点处。
bool flag[MAXN];//是否在栈里面
int belong[MAXN];//表示i节点在Tarjan之后属于什么节点。
int value[MAXN];//表示Tarjan之前的节点的价值
int behind_value[MAXN];//表示Tarjan之后的节点价值
int stack[MAXN],cnt,top,ken;//......
vector<int> line[MAXN];//使用不定长数组代替前向星,好像会简洁一点emmmm.....
vector<int>tline[561100];
int ind[561100];
void Tarjan(int now)
{//一下是固定不变的Tarjan  qwq Nein[now]=Yeasion[now]=++ken;stack[++top]=now;flag[now]=true;for(int i=0;i<line[now].size();i++){int next=line[now][i];if(!Yeasion[next]){Tarjan(next);if(Nein[next]<Nein[now])Nein[now]=Nein[next];}elseif(flag[next])Nein[now]=min(Yeasion[next],Nein[now]);}if(Nein[now]==Yeasion[now]){cnt++;//这里我们在Tarjan之后新建了一个图,然后我们资金编造了一个顺序。 int pass;//顾名思义,过去的节点嘛... do{pass=stack[top--];//更新pass,进行退栈操作。 belong[pass]=cnt;//表明原图中的pass点属于新图中的cnt节点。 behind_value[cnt]+=value[pass];//更新新图中的cnt的节点大小 flag[pass]=false;//退栈..... }while(pass!=now);}return ;
}
void link()//建新图
{for(int i=1;i<=n;i++)for(int j=0;j<line[i].size();j++){int next=line[i][j];if(belong[i]!=belong[next]){tline[belong[i]].push_back(belong[next]);ind[belong[next]]+=1;}}
}
void SPFA()
{while(!q.empty()){int pas=q.front();q.pop();inque[pas]=false;for(int i=0;i<tline[pas].size();i++){int next=tline[pas][i];if(dist[next]>dist[pas]-behind_value[next]){dist[next]=dist[pas]-behind_value[next];if(!inque[next]){inque[next]=true;q.push(next);}}}}
}
int main()
{scanf("%d%d",&n,&m);int a,b;for(int i=1;i<=m;i++) {scanf("%d%d",&a,&b);line[a].push_back(b);}for(int i=1;i<=n;i++)scanf("%d",&value[i]);for(int i=1;i<=n;i++)if(!belong[i])Tarjan(i);scanf("%d%d",&s,&p);memset(dist,127,sizeof(dist));dist[belong[s]]=-behind_value[belong[s]];q.push(belong[s]);inque[belong[s]]=true;int ans=0;for(int i=1;i<=p;i++){scanf("%d",&a);ans=min(ans,dist[belong[a]]);}printf("%d",-ans);
}

转载于:https://www.cnblogs.com/Yeasio-Nein/p/luoguP3297.html

[luoguP3627][APIO2009]抢掠计划相关推荐

  1. [APIO2009]抢掠计划

    题目描述 Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机.令人奇怪的是,Siruseri 的酒吧也都设 ...

  2. 洛谷 P3627 [APIO2009]抢掠计划 题解

    Analysis 建图+强连通分量+SPFA求最长路 但要保证最后到达的点中包含酒馆 虽然思路并不难想,但要求的代码能力很高. 1 #include<iostream> 2 #includ ...

  3. 【luogu P3627 [APIO2009]抢掠计划】 题解

    题目链接:https://www.luogu.org/problemnew/show/P3627 把点权转化到边权上去. #include <stack> #include <que ...

  4. 洛谷 P3627 [APIO2009]抢掠计划

    这题一看就是缩点,但是缩完点怎么办呢?首先我们把所有的包含酒吧的缩点找出来,打上标记,然后建立一张新图, 每个缩点上的点权就是他所包含的所有点的点权和.但是建图的时候要注意,每一对缩点之间可能有多条边 ...

  5. acmore|acmore.cc1211采油区域1212会议中心1213抢掠计划APIO2009

    采油区域: #include <iostream> #include <algorithm> #include <cstdio> #include <cstd ...

  6. bzoj 1179 抢掠计划atm (缩点+有向无环图DP)

    bzoj 1179 抢掠计划atm (缩点+有向无环图DP) 手动博客搬家: 本文发表于20170716 10:58:18, 原地址https://blog.csdn.net/suncongbo/ar ...

  7. 【BZOJ1179】[Apio2009]Atm/抢掠计划

    1179: [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MB Submit: 4701  Solved: 2087 [Submit][Sta ...

  8. 【APIO2009-3】抢掠计划

    描述 Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定,在每个路口都设立了一个 Siruseri 银行的 ATM 取款机. 令人奇怪的是, Siruseri 的酒吧也都设在 ...

  9. 非递归!APIO2009atm[抢掠计划]题解

    题目描述 输入描述 Input Description 第一行包含两个整数N.M.N 表示路口的个数,M 表示道路条数.接下来 M 行,每行两个整数,这两个整数都在1 到N 之间,第i+1 行的两个整 ...

  10. SCAU-春季训练-不应该啊(怎么这么菜。。。)

    2021/3/14 春季训练2(难度div2d) 反思:(赛前,看什么crt,赛时满脑子都是线性方程组,....................................) 最近表现都不太好.. ...

最新文章

  1. 网络异常_网络异常易频发,流量分析来排查
  2. Python代码编写过程中有哪些重要技巧?
  3. VS2017 安装程序清单签名验证失败
  4. 【Git】将 GitHub 工程设置为私有库 ( 登录账号 | 工程主页 | Settings | Danger Zone | Change visibility | Make private )
  5. cef谷歌内核浏览器获取cookie值并保存
  6. java中用iterator去检查最大值_Java中的Iterator vs forEach
  7. DOM2-document操作
  8. android 枚举类型比较大小写,Spring 3.0 MVC绑定枚举区分大小写
  9. 深入理解javascript函数参数
  10. P7909 [CSP-J 2021] 分糖果 方法二
  11. (28)自动化构建工具Gulp
  12. 7.23 ToolTip 实现全介绍
  13. spark入门(1)
  14. ios下拉效果滑动滚出页面
  15. office相关文件转pdf的几种方式
  16. The Innovation | Volume 3 Issue 3 Live Now
  17. Apache Storm-2011
  18. xshell6家用版下载和使用
  19. DPDK报错:Ethdev port_id=0 requested Rx offloads 0xe doesn‘t match Rx offloads capabilities 0x800
  20. 听高级产品经理来聊一聊,什么是产品架构

热门文章

  1. C语言编程练习:定义判断素数函数int isPrime(int n);若n是素数返回1,否则返回0。调用isPrime函数,输出2~1000之内所有素数,按一行10个素数形式输出。
  2. 使用dockerfile创建一个包含jdk和tomcat的镜像
  3. 【OP-TEE】TA的加载(超详细)
  4. 第五篇 应用Java
  5. mapper扫描问题(Invalid bound statement (not found))
  6. Git之深入解析如何解决.git目录过大的问题
  7. .net npoi 导出合并单元格
  8. 错误异常too many open files解决方法
  9. DRS是啥你都不知道?不是吧,不是吧
  10. 【1】EFR32配置433Mhz(可通信CC1101)——EFR32 项目例程打开和烧录