思路 : 这道题是一道Tarjan + 最长路的题。首先,我们用Tarjan把每个强连通分量缩成一个点,并记录那个强连通分量的点权和(因为当那个人走进一个强连通分量后那个强连通分量中的所有money都会被他拿走(绕一圈不就完了?)),然后我们化点权为边权,再以起点所在的强连通分量跑最长路,最后就能计算出从起点所在的强连通分量到任意一个终点所在的强连通分量的最长距离了(最大money值),输出的是取从起点所在的强连通分量到任意一个终点所在的强连通分量的最大值。


细节问题 :

  • 关于如何把点权转化为边权:很简单,设u -> k有一条路,q[i]表示点i的权值,边的权值就是q[u],最后我们只需把q[最后一个点的权值(终点)]加上就好了。
  • 关于如何建边:只需把不在同一个强连通分量中的可以连接的边连起来就好了(注意:是连两个点所在的的强连通分量)。
  • 关于如何跑最长路:我们只学过最短路,但没学过该如何跑最长路,所以我们化未知变为已知,把最长路化为最短路。你们仔细想一想,如果我们把边权建为负的,是不是就可以跑最短路了?最后再把距离 * -1 不就完了?

code:

 #include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
stack < int > pru;
int n, m, p, head[], q[], col[], color, dfn[], low[], s, e[], sum[], z, num, vis[], dis[], ans;//变量太多懒得解释,意会一下吧。。。
struct node//存边
{
int next, to, val;
}stu[];
queue < node > G;//用于临时存放边
inline void add(int x, int y, int z)
{
stu[++num].next = head[x];
stu[num].to = y;
stu[num].val = z;
head[x] = num;
return;
}
inline void tarjan(int u)//Tarjan算法,这里用于缩点
{
dfn[u] = low[u] = ++z;
vis[u] = ;
pru.push(u);
for(register int i = head[u]; i; i = stu[i].next)
{
int k = stu[i].to;
if(!vis[k])
{
tarjan(k);
low[u] = min(low[u], low[k]);
}
else if(!col[k])
{
low[u] = min(low[u], dfn[k]);
}
}
if(dfn[u] == low[u])
{
col[u] = ++color;
sum[color] += q[u];//权值和
while(pru.top() != u)
{
col[pru.top()] = color;
sum[color] += q[pru.top()];//权值和
pru.pop();
}
pru.pop();
}
return;
}
inline void spfa(int s)//求最短路模板SPFA
{
queue < int > pru;
memset(vis, , sizeof(vis));
memset(dis, INF, sizeof(dis));
pru.push(s);
dis[s] = ;
vis[s] = ;
while(!pru.empty())
{
int u = pru.front();
pru.pop();
vis[u] = ;
for(register int i = head[u]; i; i = stu[i].next)
{
int k = stu[i].to;
if(dis[k] > dis[u] + stu[i].val)
{
dis[k] = dis[u] + stu[i].val;
if(!vis[k])
{
vis[k] = ;
pru.push(k);
}
}
}
}
return;
}
inline void init()//初始化
{
memset(head, , sizeof(head));
for(register int i = ; i <= ; ++i)
{
stu[i].next = ;
stu[i].to = ;
stu[i].val = ;
}
num = ;
return;
}
inline void add_edge()
{
for(register int u = ; u <= n; ++u)
{
for(register int i = head[u]; i; i = stu[i].next)
{
int k = stu[i].to;
if(col[k] != col[u])//不在一个强连通分量中才建边
{
//需要临时先放到G里,因为如果还没有把那些一大堆东西初始化就又建边,会.......
G.push(node{col[u], col[k], -sum[col[u]]});//要建负边权(这样可以把最长路转化为最短路)
}
}
}
init();//初始化
while(!G.empty())//初始化完再存边
{
node p = G.front();
add(p.next, p.to, p.val);//建边
G.pop();
}
return;
}
signed main()
{
scanf("%d %d", &n, &m);
for(register int i = , x, y; i <= m; ++i)
{
scanf("%d %d", &x, &y);
add(x, y, );
}
for(register int i = ; i <= n; ++i)
{
scanf("%d", &q[i]);
}
scanf("%d %d", &s, &p);
for(register int i = ; i <= p; ++i)
{
scanf("%d", &e[i]);
}
for(register int i = ; i <= n; ++i)
{
if(!vis[i])
{
tarjan(i);
}
}
add_edge();//建边
spfa(col[s]);//从起点所在的强连通分量中开始
for(register int i = ; i <= p; ++i)
{
ans = max(ans, dis[col[e[i]]] * -/*别忘了把它变回正数*/ + sum[col[e[i]]]/*别加上终点所在的强联通分量的权值*/);
}
printf("%d", ans);
return ;
}

洛谷 P3627 【抢掠计划】的更多相关文章

  1. 【题解】洛谷P3627 [APIO2009]抢掠计划(缩点+SPFA)

    洛谷P3627:https://www.luogu.org/problemnew/show/P3627 思路 由于有强连通分量 所以我们可以想到先把整个图缩点 缩点完之后再建一次图 把点权改为边权 并 ...

  2. 洛谷 P1251 餐巾计划问题(线性规划网络优化)【费用流】

    (题外话:心塞...大部分时间都在debug,拆点忘记加N,总边数算错,数据类型标错,字母写错......) 题目链接:https://www.luogu.org/problemnew/show/P1 ...

  3. 洛谷 P2680 运输计划-二分+树上差分(边权覆盖)

    P2680 运输计划 题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条 ...

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

    抢掠计划 题目链接 比较水的缩点模板题,Tarjan缩点,重新建图,记录联通块的钱数.是否有酒吧 DAG上记忆化搜索即可 #include<iostream> #include<cs ...

  5. BZOJ4326或洛谷2680 运输计划

    BZOJ原题链接 洛谷原题链接 用\(LCA\)初始化出所有运输计划的原始时间,因为答案有单调性,所以二分答案,然后考虑检验答案. 很容易想到将所有超出当前二分的答案的运输计划所经过的路径标记,在这些 ...

  6. loj2734「JOISC 2016 Day 2」女装大佬 || 洛谷P3615 如厕计划

    loj2734 洛谷P3615 http://218.5.5.242:9021/problem/185 不会做... 题解(来自ditoly): 这一步更详细的解释(来自kkksc03): 还是从后面 ...

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

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

  8. 洛谷P3627[APOI2009] (讨厌的)抢掠计划

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

  9. 洛谷 P3627 [APIO2009](抢掠计划 缩点+spfa)

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

随机推荐

  1. UltraEdit不自动生成保存备份文件(.bak)

    UltraEdit修改文件或格式化文件保存后会生成烦人的.bak文件. 去掉该功能办法如下: 高级 -> 配置 -> 文件处理 -> 备份 “保存时备份文件”选择“不备份” (Adv ...

  2. Mybatis整合Spring 使用

    1.继承通用的Mapper<T>,必须指定泛型<T> 例如下面的例子: public interface UserInfoMapper extends Mapper<Us ...

  3. 前端工程师和设计师必备的chrome插件

    Google Chrome是最好用的几个浏览器之一,今天我来分享下自己收集的一系列Chrome插件,希望对大家的学习和工作有帮助. 注:你可以通过复制链接或者在谷歌商店搜索相应插件的名称来获取以下插件 ...

  4. 详解 Diff 算法以及循环要加 key 值问题

    上一篇文章我简述了什么是 Virtual DOM,这一章我会详细讲 Diff 算法以及为什么在 React 和 Vue 中循环都需要 key 值. 什么是 DOM Diff 算法 Web 界面其实就是 ...

  5. 在.NET CORE中使用配置文件:对 ConfigurationBuilder 的使用说明

    示例:ASP.NET MVC 使用示例: 如何覆写默认行为?如取消热更新支持,方法如下: 示例:控制台 使用应用程序参数 使用键值对枚举(这里以字典来说明) 使用JSON文件 注册配置文件中的某一个段 ...

  6. 在 树莓派(Raspberry PI) 中使用 Docker 运行 MySQL

    在 树莓派(Raspberry PI) 中使用 Docker 运行 MySQL 本文主要利用 biarms 提供的 Dockerfile 进行安装. 笔者最新发现! MySQL 5.7 Docker ...

  7. 【Java笔记】【Java核心技术卷1】chapter3 D2注释

    package chapter3; /** * 文档注释 *@author lp *@version 1 **/ public class D2注释 { //单行注释 /* 长注释 */ }

  8. java虚拟机学习笔记(五)---运行时的数据区域

    Java虚拟机所管理的内存包括以下几个运行时的数据区域:方法区,堆,虚拟机栈,本地方法栈,程序计数器.下面对其进行介绍: 程序计数器 它是一块较小的内存空间,可以看做当前线程做执行的字节码的信号指示器 ...

  9. redhat linux 5.3修改Java环境变量

    需要配置的环境变量 1. PATH环境变量.作用是指定命令搜索路径,在shell下面执行命令时,它会到PATH变量所指定的路径中查找看是否能找到相应的命令程序.我们需要把jdk安装目录下的bin目录增 ...

  10. Spark1——介绍

    1.Spark是什么 Spark是一个用来实现快速而通用的集群计算的平台. 2.Spark是一个大一统的软件栈 Spark项目包含多个紧密集成的组件.首先Spark的核心是一个对由很多计算任务组成的. ...