思路 : 这道题是一道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. 第一章: 初识Java

    计算机程序:计算机为完成某些功能产生的一系列有序指令集合. Java技术包括:JavaSE(标准版) JavaEE(企业版) ---JavaME(移动版) 开发Java程序步骤:1.编写 2.编译 3 ...

  2. Appium+python自动化(二十五)- 那些让人抓耳挠腮、揪头发和掉头发的事 - 获取控件ID(超详解)

    简介 在前边的第二十二篇文章里,已经分享了通过获取控件的坐标点来获取点击事件的所需要的点击位置,那么还有没有其他方法来获取控件点击事件所需要的点击位置呢?答案是:Yes!因为在不同的大小屏幕的手机上获 ...

  3. Waiting for 1 instance(s) to be deallocated

    看是不是马虎,自己的xampp,也就是mysql有没有打开

  4. Another option to bootup evidence files

    When it comes to booting up evidence files acquired from target disk, you got two options. One is VF ...

  5. java8-流的操作

    流的操作 流的使用一般包括三件事: 一个数据源来执行一个查询; 一个中间操作链,形成一条流的流水线; 一个终端操作,执行流水线,并能生成结果 中间操作 操作 类型 返回类型 操作参数 函数描述符 fi ...

  6. 【一些小常识】Linux文件目录的通配符用法/*

    在使用linux命令的时候,一时有点搞不清*的用法,于是整理记录下,在做jenkins 持续集成时还是很有用的 “*”在通配符中是最常用的一种,主要整理下在使用Linux命令时,文件夹目录的用法. 1 ...

  7. 2、JAVA相关基础的学习和工具

    个人感觉,各种语言的基础知识,例如标识符,运算符等在宏观上几乎是一样的,只是在某些方面上会有一点点差异,因为本人已经有了语言基础,所以对于标识符,关键字,运算符等方面的只是便不作赘述,敬请谅解,如果你 ...

  8. FutrueTask原理及源码分析

    1.前言 相信很多人了解到FutureTask是因为ThreadPoolExecutor.submit方法,根据ThreadPoolExecutor.submit的使用,我们可以先猜一下FutureT ...

  9. Java.基础 -------- 一个Java源文件中可以有很多类,但只能有一个类是public的

    一个Java源文件中可以有很多类,但只能有一个类是public的        Java程序是从一个public类main函数开始执行的,只能有一个public是为了给类装载器提供方便,一个publi ...

  10. node获取本机动态IP,并对应修改相关JavaScript文件的IP地址

    目录 由于本机是自动获取分配的动态IP,所以每次重启后需要重新更改与IP相关文件 参考 时间:2018-08-02,更新时间:2018-11-06 注意:在win10环境运行无问题 由于本机是自动获取 ...