强掠计划

题目大意:

\(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. 哦,Vendor

    vendor踩坑笔记: 接过公司里面X平台golang部分的后端后,需要新添加一个业务功能,美滋滋~ 拿过项目一顿写之后后遇到事了. 报错的描述如下: 报错的大意说:方法的入参类型不匹配,我们不能把 ...

  2. 第03组 Alpha(2/4)

    队名:不等式方程组 组长博客 作业博客 团队项目进度 组员一:张逸杰(组长) 过去两天完成的任务: 文字/口头描述: 制定了初步的项目计划,并开始学习一些推荐.搜索类算法 GitHub签入纪录: 暂无 ...

  3. Nginx解决前端调用后端接口跨域问题

    1.项目中遇到的问题描述: 前端调用zuul统一网关服务接口,请求状态码200,但是无返回数据. 浏览器控制台报错信息:No  Access-Control-Allow-Origin header i ...

  4. Linux命令总结大全,包含所有linux命令

    使用说明:此文档包含所有的Linux命令,只有你想不到的没有你看不到的,此文档共计10万余字,有8400多行,预计阅读时间差不多需要3个小时左右,所以要给大家说一说如何阅读此文档 为了方便大家阅读,我 ...

  5. Alink漫谈(七) : 如何划分训练数据集和测试数据集

    Alink漫谈(七) : 如何划分训练数据集和测试数据集 目录 Alink漫谈(七) : 如何划分训练数据集和测试数据集 0x00 摘要 0x01 训练数据集和测试数据集 0x02 Alink示例代码 ...

  6. Unit2-窝窝牌电梯

    全文共2329字,推荐阅读时间10~15分钟. 文章共分四个部分: 作业分析 评测相关 重构策略 课程体验感受 作业分析 Unit2要求我们模拟现实生活中的电梯调度情景,迭代路径是单电梯->多电 ...

  7. Com训练_1

    初次接触Com大概是2001年,离现在多年了,那时认识比较肤浅,再次接触学习下. //ComPort + D7, 稍后将训练ComPort6 + D10.3.2环境 //MSComm + D7,D10 ...

  8. 一文读懂Redis的四种模式,单机、主从、哨兵、集群

    少点代码,多点头发 本文已经被GitHub收录,欢迎大家踊跃star 和 issues. https://github.com/midou-tech/articles 入职第一周,我被坑了 最近刚入职 ...

  9. QT creator视频教程分享

    Qt Creator快速入门(第3版) [霍亚飞著] 完整pdf扫描版[92MB] 附随书源码,资源收集于网络,供参考 https://pan.baidu.com/s/1pLQdIUR kjaf ht ...

  10. Azure AD B2C(二)使用Azure AD B2C为ASP.NET Core 应用设置社交帐户(邮箱)登录/注册

    一,引言 上次关于Azure AD B2C 讲到一些概念,有介绍到,Azure AD B2C 也是一种身份验证的解决方案,但是它运行客户使用其首选的社交,企业或者本地账户标识对应用程序和API进行单一 ...