APIO强掠计划(spfa+tarjan缩点)
强掠计划
题目大意:
\(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缩点)的更多相关文章
- Tarjan缩点+Spfa最长路【p3627】[APIO2009] 抢掠计划
Description Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机.令人奇怪的是,Siruseri ...
- 洛谷 P3627 [APIO2009]抢掠计划 Tarjan缩点+Spfa求最长路
题目地址:https://www.luogu.com.cn/problem/P3627 第一次寒假训练的结测题,思路本身不难,但对于我这个码力蒟蒻来说实现难度不小-考试时肛了将近两个半小时才刚肛出来. ...
- [Usaco2015 Jan]Grass Cownoisseur Tarjan缩点+SPFA
考试的时候忘了缩点,人为dfs模拟缩点,没想到竟然跑了30分,RB爆发... 边是可以重复走的,所以在同一个强连通分量里,无论从那个点进入从哪个点出,所有的点一定能被一条路走到. 要使用缩点. 然后我 ...
- 【bzoj1179】[Apio2009]Atm Tarjan缩点+Spfa最长路
题目描述 输入 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每 ...
- [BZOJ1179] [Apio2009]Atm(tarjan缩点 + spfa)
传送门 题意 N个点M条边的有向图 每个点有点权 从某一个结点出发 问能获得的最大点权和 一个点的点权最多被计算一次 N<=500000 M<=500000 思路 先tarjan缩点,然后 ...
- 强连通分量tarjan缩点——POJ2186 Popular Cows
这里的Tarjan是基于DFS,用于求有向图的强联通分量. 运用了一个点dfn时间戳和low的关系巧妙地判断出一个强联通分量,从而实现一次DFS即可求出所有的强联通分量. §有向图中, u可达v不一定 ...
- UVA 11324.The Largest Clique tarjan缩点+拓扑dp
题目链接:https://vjudge.net/problem/UVA-11324 题意:求一个有向图中结点数最大的结点集,使得该结点集中任意两个结点u和v满足:要目u可以到达v,要么v可以到达u(相 ...
- Tarjan&&缩点简析
由于昨天写计蒜客初赛的一道题,看出了是缩点,但一时忘记了另外一个叫什么s...的算法怎么写了,话说我为什么没有回去翻一下自己的blog然后今天就去学了更实用也更强力的Tarjan Tarjan的思想其 ...
- [HAOI2006]受欢迎的牛 tarjan缩点 + 拓扑排序
---题面--- 题解: 首先tarjan缩点应该还是容易想到的,因为喜爱具有传递性,所以一个强联通分量里面的点实际上是全部等效的,所以我们可以缩成一个方便判断, 缩完点之后整张图就变成了一个有向无环 ...
随机推荐
- Linux帮助命令man详解
命令man详解 命令man,可以获得命令(使用whatis命令可以得到一个命令的简短介绍,可以使用:命令 --help 来获得命令的选项说明)或配置文件的帮助信息(可以使用apropos命令仅查看配置 ...
- 浅谈js运行机制
前言 因为js的运行机制十分重要,理解起来也十分抽象,仍还是在这里做个记录,加深自己的记忆. 总之,希望本文的内容能够对您的学习或者工作有所帮助.另,如果有任何的错误或者不足请指正! 如何理解js单线 ...
- Java设计模式之亨元模式
之前在项目中接触过亨元模式这一种设计模式,当时因为项目赶进度,因此只不过是大概的了解了一下,刚好今天有时间,就写一篇博客详细的学习一下亨元模式. 一.概念 运用共享技术有效的支持大量细粒度的对象.(来 ...
- 数据结构与算法-python描述-单向循环链表
# coding:utf-8 # 单向循环链表的相关操作: # is_empty() 判断链表是否为空 # length() 返回链表的长度 # travel() 遍历 # add(item) 在头部 ...
- 3.vue计算属性
1.计算属性 再vue中如果出现表达式过长或者逻辑比较复杂,这时会导致代码不清晰,臃肿,难以维护所以我们会使用计算属性进行书写 再计算属性中可以放负责的逻辑,可以是函数,表达式等,但最终会返回一个 ...
- 微信weixin://xxx 分析
通过weixin://来打开微信客户端: <a href="weixin://">打开微信</a> <a href="weixin://dl ...
- Pyinstaller 打包python 到exe 在windows下免python环境运行python
在创建了独立应用(自包含该应用的依赖包)之后,还可以使用 PyInstaller 将 Python 程序生成可直接运行的程序,这个程序就可以被分发到对应的 Windows 或 Mac OS X 平台上 ...
- C++入门-控制台版的通讯录管理系统
通讯录管理系统 1.系统需求 通讯录是一个可以记录亲人.好友信息的工具. 本教程主要利用C++来实现一个通讯录管理系统 系统中需要实现的功能如下: 添加联系人:向通讯录中添加新人,信息包括(姓名.性别 ...
- 良心之作送你几个Xsheel使用小技巧
❝ 工作中无可避免的会使用到Xsheel,接下来咔咔给你介绍几个小技巧,让你工作游刃有余. ❞ 一.告别繁琐 你的Xsheel连接后是不是这样的 哦!这个也太烦了我至少得在敲俩次命令才能到我的工作目录 ...
- 基于flask框架的高校舆情分析系统
系统分析: 高校舆情分析拟实现如下功能,采集微博.贴吧.学校官网的舆情信息,对这些舆情进行数据分析.情感分析,提取关键词,生成词云分析,情感分析图,实时监测舆情动态. 系统设计: 前端:采用layui ...