强掠计划

题目大意:

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

\(Banditji\) 计划实施 \(Siruseri\) 有史以来最惊天动地的 抢劫。他将从市中心出发,沿着单向道路行驶,抢劫所有他途径的 \(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\) 机中的钱数 \(ai\)​。

接下来一行包含两个整数 \(S,P\),\(S\) 表示市中心的编号,也就是出发的路口。\(P\) 表示酒吧数目。

接下来的一行中有 \(P\) 个整数,表示 \(P\) 个有酒吧的路口的编号。

输出格式

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

输入输出样例

输入

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

题目思路:

这道题的主要思路就是tarjan先预处理一下。就这个例子说,我们可以看到1,2,4形成了一个权环,于是便可以把他们三个缩成一个点,然后再把原有的边连起来,然后求一个从开始的点开始的单源spfa,最后枚举酒吧的钱数求最大值。思路很清晰,缩点+spfa,主要还是看模板打的熟不熟练了。

废话不多说,上代码

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int Maxx = 1e7 + 10, INF = 0x3f3f3f3f; int n, m;
int len, Head[Maxx], To[Maxx], from[Maxx], path[Maxx], t[Maxx];//cun
int len_, H[Maxx];
int low[Maxx], dfn[Maxx], stk[Maxx], top, num, belong[Maxx], cnt;//tarjan
long long w[Maxx];
bool vis[Maxx];
long long dis[Maxx]; struct Edge {
int to, next;
} edge[Maxx], E[Maxx]; void addedge1(int a, int b) {
edge[++len].to = b;
edge[len].next = Head[a];
Head[a] = len;
}
void addedge2(int a, int b) {
E[++len_].to = b;
E[len_].next = H[a];
H[a] = len_;
} void tarjan(int u) {
low[u] = dfn[u] = ++num;
stk[++top] = u;
for (int x = Head[u]; x; x = edge[x].next) {
int v = edge[x].to;
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if (!belong[v])
low[u] = min(low[u], dfn[v]);
}
if (low[u] == dfn[u]) {
++cnt;
while (1) {
int x = stk[top--];
belong[x] = cnt;
w[cnt] += path[x];
if (x == u) break;
}
}
} void spfa(int s, int n) {
queue<int> que;
for (int i = 1; i <= n; i++) dis[i] = -INF, vis[i] = 0;
dis[s] = w[s];
que.push(s);
vis[s] = 1;
while (!que.empty()) {
int u = que.front();
que.pop();
vis[u] = 0;
for (int i = H[u]; i; i = E[i].next) {
int v = E[i].to;
if (dis[v] < dis[u] + w[v]) {
dis[v] = dis[u] + w[v];
if (!vis[v]) {
que.push(v);
vis[v] = 1;
}
}
}
}
} void solve(){
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
scanf("%d%d", &from[i], &To[i]);
addedge1(from[i], To[i]);
}
for (int i = 1; i <= n; i++) {
scanf("%d", &path[i]);
}
int s, P;
for (int i = 1; i <= n; i++)
if (!dfn[i]) tarjan(i); scanf("%d%d", &s, &P);
s = belong[s];
int ansnum = 0;
for (int i = 1; i <= P; i++) {
int a;
scanf("%d", &a);
if (!vis[belong[a]]) {
t[++ansnum] = belong[a];
vis[belong[a]] = 1;
}
}
for (int i = 1; i <= m; i++) {
int u = belong[from[i]], v = belong[To[i]];
if (u != v) addedge2(u, v);
}
spfa(s, cnt);
long long ans = -INF;
for (int i = 1; i <= ansnum; i++) {
ans = max(ans, dis[t[i]]);
}
printf("%lld", ans);
} int main(){
solve();
return 0;
}

谢谢观看

APIO强掠计划(spfa+tarjan缩点)的更多相关文章

  1. Tarjan缩点+Spfa最长路【p3627】[APIO2009] 抢掠计划

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

  2. 洛谷 P3627 [APIO2009]抢掠计划 Tarjan缩点+Spfa求最长路

    题目地址:https://www.luogu.com.cn/problem/P3627 第一次寒假训练的结测题,思路本身不难,但对于我这个码力蒟蒻来说实现难度不小-考试时肛了将近两个半小时才刚肛出来. ...

  3. [Usaco2015 Jan]Grass Cownoisseur Tarjan缩点+SPFA

    考试的时候忘了缩点,人为dfs模拟缩点,没想到竟然跑了30分,RB爆发... 边是可以重复走的,所以在同一个强连通分量里,无论从那个点进入从哪个点出,所有的点一定能被一条路走到. 要使用缩点. 然后我 ...

  4. 【bzoj1179】[Apio2009]Atm Tarjan缩点+Spfa最长路

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

  5. [BZOJ1179] [Apio2009]Atm(tarjan缩点 + spfa)

    传送门 题意 N个点M条边的有向图 每个点有点权 从某一个结点出发 问能获得的最大点权和 一个点的点权最多被计算一次 N<=500000 M<=500000 思路 先tarjan缩点,然后 ...

  6. 强连通分量tarjan缩点——POJ2186 Popular Cows

    这里的Tarjan是基于DFS,用于求有向图的强联通分量. 运用了一个点dfn时间戳和low的关系巧妙地判断出一个强联通分量,从而实现一次DFS即可求出所有的强联通分量. §有向图中, u可达v不一定 ...

  7. UVA 11324.The Largest Clique tarjan缩点+拓扑dp

    题目链接:https://vjudge.net/problem/UVA-11324 题意:求一个有向图中结点数最大的结点集,使得该结点集中任意两个结点u和v满足:要目u可以到达v,要么v可以到达u(相 ...

  8. Tarjan&&缩点简析

    由于昨天写计蒜客初赛的一道题,看出了是缩点,但一时忘记了另外一个叫什么s...的算法怎么写了,话说我为什么没有回去翻一下自己的blog然后今天就去学了更实用也更强力的Tarjan Tarjan的思想其 ...

  9. [HAOI2006]受欢迎的牛 tarjan缩点 + 拓扑排序

    ---题面--- 题解: 首先tarjan缩点应该还是容易想到的,因为喜爱具有传递性,所以一个强联通分量里面的点实际上是全部等效的,所以我们可以缩成一个方便判断, 缩完点之后整张图就变成了一个有向无环 ...

随机推荐

  1. Java实现第八届蓝桥杯包子凑数

    包子凑数 题目描述 小明几乎每天早晨都会在一家包子铺吃早餐.他发现这家包子铺有N种蒸笼,其中第i种蒸笼恰好能放Ai个包子.每种蒸笼都有非常多笼,可以认为是无限笼. 每当有顾客想买X个包子,卖包子的大叔 ...

  2. Linux 重装MySQL

    1.首先查看当前MySQL的安装情况,查找之前是否安装了MySQL rpm -qa|grep -i mysql 可以看到如下图: 因为我是使用的宝塔面板一键安装的LAMP,所以显示安装了bt-mysq ...

  3. node实现图片分割

    前言 最近,女王大大日常找我弄图片,本来之前我一直是ps帮他弄得,后来- -,ps不能分割过长的图片,我就想想能不能通过代码来帮他实现好了. 经过我在npm搜索一番,发现没有一个纯代码层面的high ...

  4. js数据劫持 Object.defineProperty() 作用

    原生js Object.defineProperty() 作用 假设我们有一个obj对象,我们要给他设置一个name属性会这么做 Object.defineProperty()也可以设置对象属性 这个 ...

  5. Nginx 的变量究竟是怎么一回事?

    之前说了很多关于 Nginx 模块的内容,还有一部分非常重要的内容,那就是 Nginx 的变量.变量在 Nginx 中可以说无处不在,认识了解这些变量的作用和原理同样是必要的,下面几乎囊括了关于 Ng ...

  6. excel 如何制作带下拉框的动态折线图表

    首先我们需要有个类似下图产品销量的基础数据表. 首先将光标放入表格中任意位置,然后插入一个不带点标记的折线图,然后将折线的颜色设置为灰色. 第一次设置成灰色后,一定善用f4快捷键进行快速的折线颜色设置 ...

  7. Mac 电脑查看 pkg包的安装路径

    pkgutil --pkgspkgutil --infopkgutil --files

  8. 01 . MongoDB简介及部署配置

    简介 什么是MongoDB? MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统. 在高负载的情况下,添加更多的节点,可以保证服务器性能. MongoDB 旨在为WEB应用 ...

  9. unittest模块在linux报错: AttributeError: module 'unittest' has no attribute 'TestRunner'

    一开始在windows下运行没有问题,但是在linux下运行却报如下错误: ​ AttributeError: module 'unittest' has no attribute 'TestRunn ...

  10. Oracle调用Java方法(下)复杂Jar包封装成Oracle方法以及ORA-29521错误

    上一篇随笔中已经说了简单的Jar是如何封装的,但是我的需求是根据TIPTOP的查询条件产生XML文件并上传到FTP主机中,那么就要涉及到XML生成的方法和FTP上传的方法 所以在Eclipse写的时候 ...