题目描述

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

Banditji 计划实施 Siruseri 有史以来最惊天动地的 ATM 抢劫。他将从市中心 出发,沿着单向道路行驶,抢劫所有他途径的 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 机中的钱数。接下来一行包含两个整数 S、P,S 表示市中心的 编号,也就是出发的路口。P 表示酒吧数目。接下来的一行中有 P 个整数,表示 P 个有酒吧的路口的编号。

输出格式:

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

输入输出样例

输入样例#1:

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
输出样例#1:

47

说明

50%的输入保证 N, M<=3000。所有的输入保证 N, M<=500000。每个 ATM 机中可取的钱数为一个非负整数且不超过 4000。

输入数据保证你可以从市中心 沿着 Siruseri 的单向的道路到达其中的至少一个酒吧。

这道题略加分析,便可知是强连通+最长路径。

强连通可以用tarjan,最长路可以用拓扑或spfa.

两个裸的算法。

注意:在强连通中,我们可以直接使用点权进行缩点

但在最长路径中,我们就得将点权等效替换成边权进行计算;

 #include<bits/stdc++.h>
using namespace std;
#define man 500010
/*tarjan*/
int dfn[man],low[man],sta[man],bel[man],msum[man];
int dep=,top=,cnt=;
bool vis[man];
/*edge*/
int head[man<<],num=,dis[man];
struct edge
{
int next,to,dis;
}e[man<<];
inline void add(int from,int to,int dis)
{
e[++num].next=head[from];
e[num].to=to;
e[num].dis=dis;
head[from]=num;
}
inline void clear()
{
memset(e,,sizeof(e));
memset(head,,sizeof(head));
memset(vis,,sizeof(vis));
num=;
}
/*common*/
int n,m,cost[man],id[man],st,p,x[man],y[man];
inline void tarjan(int s)
{
dfn[s]=low[s]=++dep;
vis[s]=;sta[++top]=s;
for(int i=head[s];i;i=e[i].next)
{ int to=e[i].to;
if(!dfn[to])
{ tarjan(to);
low[s]=min(low[s],low[to]);
}
else if(vis[to])
low[s]=min(low[s],dfn[to]);
}
if(low[s]==dfn[s])//需熟练掌握这一段的写法
{ int j;++cnt;
do
{ j=sta[top--];
bel[j]=cnt;//缩点
msum[cnt]+=cost[j];//计算联通块的权值
vis[j]=;
}while(j!=s);
}
} inline void spfa(int s)
{ queue<int >q;
for(int i=;i<=cnt;i++) dis[i]=;
dis[s]=;vis[s]=;q.push(s);
do
{ int u=q.front();q.pop();vis[u]=;
for(int i=head[u];i;i=e[i].next)
{ int to=e[i].to;
if(dis[to]>dis[u]+e[i].dis)
{ dis[to]=dis[u]+e[i].dis;
if(!vis[to])
{ vis[to]=;
q.push(to);
}
}
}
}while(q.size());
} int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=;i<=m;i++)
{
cin>>x[i]>>y[i];
add(x[i],y[i],);
}
for(int i=;i<=n;i++)
cin>>cost[i];
cin>>st>>p;
for(int i=;i<=p;i++)
cin>>id[i];
for(int i=;i<=n;i++)
if(!dfn[i])
tarjan(i);
clear();
for(int i=;i<=m;i++)//通过将边权取反求出最长路
{
if(bel[x[i]]!=bel[y[i]])
{
add(bel[x[i]],bel[y[i]],-msum[bel[y[i]]]);
}
}
spfa(bel[st]);
int ans=-;
for(int i=;i<=p;i++)
{
ans=max(ans,-dis[bel[id[i]]]);}
cout<<ans+msum[bel[st]]<<endl;//根据最短路的特点,加上出发点的权值
return ;
}

发现自己的强连通分量写的不熟练,需大量练习。

洛谷 P3627 [APIO2009](抢掠计划 缩点+spfa)的更多相关文章

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

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

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

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

  3. 洛谷 P3627 [APIO2009]抢掠计划

    这题一看就是缩点,但是缩完点怎么办呢?首先我们把所有的包含酒吧的缩点找出来,打上标记,然后建立一张新图, 每个缩点上的点权就是他所包含的所有点的点权和.但是建图的时候要注意,每一对缩点之间可能有多条边 ...

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

    题目大意:给你一张$n(n\leqslant5\times10^5)$个点$m(m\leqslant5\times10^5)$条边的有向图,有点权,给你起点和一些可能的终点.问从起点开始,到任意一个终 ...

  5. 洛谷 P3627 [APIO2009]抢掠计划 题解

    Analysis 建图+强连通分量+SPFA求最长路 但要保证最后到达的点中包含酒馆 虽然思路并不难想,但要求的代码能力很高. #include<iostream> #include< ...

  6. 洛谷 P3627 【抢掠计划】

    题库:洛谷 题号:3627 题目:抢掠计划 link:https://www.luogu.org/problem/P3627 思路 : 这道题是一道Tarjan + 最长路的题.首先,我们用Tarja ...

  7. BZOJ1179或洛谷3672 [APIO2009]抢掠计划

    BZOJ原题链接 洛谷原题链接 在一个强连通分量里的\(ATM\)机显然都可被抢,所以先用\(tarjan\)找强连通分量并缩点,在缩点的后的\(DAG\)上跑最长路,然后扫一遍酒吧记录答案即可. # ...

  8. 洛谷3627 [APIO2009]抢掠计划

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

  9. P3627 [APIO2009]抢掠计划

    P3627 [APIO2009]抢掠计划 Tarjan缩点+最短(最长)路 显然的缩点...... 在缩点时,顺便维护每个强连通分量的总权值 缩完点按照惯例建个新图 然后跑一遍spfa最长路,枚举每个 ...

随机推荐

  1. 启动Oracle数据库时报错ORA-00119 & ORA-00132

    今天启动Oracle数据库时报错ORA-00119 & ORA-00132,找到解决方法做个记录,方便日后查看. 若是ORACLE不提示错误的话,可以自己查看ORACLE的日志文件. Orac ...

  2. Unit02: 参数值注入 、 基于注解的组件扫描

    Unit02: 参数值注入 . 基于注解的组件扫描 (4)IOC (Inversion Of Controll 控制反转) 什么是IOC? 对象之间的依赖关系由容器来建立. 什么是DI? (Depen ...

  3. Django 组件-ModelForm

    ModelForm 组件功能就是把model和form组合起来. 首先导入ModelForm from django.forms import ModelForm 在视图函数中,定义一个类,比如就叫S ...

  4. [转载,感觉写的非常详细]DUBBO配置方式详解

    [转载,感觉写的非常详细]DUBBO配置方式详解 原文链接:http://www.cnblogs.com/chanshuyi/p/5144288.html DUBBO 是一个分布式服务框架,致力于提供 ...

  5. CentOS7 系统菜单中添加快捷方式

    一,在桌面新建一个文件 文件名随意,但必须带有.desktop的后缀名, 以Eclipse为例 vi /usr/share/applications/eclipse.desktop 二,在文件中写入如 ...

  6. Java:类与继承(隐藏和覆盖的问题)

    盒子先生金金   Java:类与继承(隐藏和覆盖的问题) Java:类与继承   Java:类与继承 对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础.抽象.封装.继承.多态这四大特性都离不 ...

  7. Windows 10 提权漏洞复现及武器化利用

    项目地址:https://github.com/SandboxEscaper/randomrepo 相关工具的下载地址: Process Explorer:https://docs.microsoft ...

  8. GDI/GDI+这些破事

    本文是杂篇,纯属笔记,想到哪写到那! 1.获取像素的RGB以及填充 CPaintDC dc(m_hWnd); COLORREF color=dc.GetPixel(,); int R=GetRValu ...

  9. Java语言主要特点有哪些?

    1.简单 Java最初是为对家用电器进行集成控制而设计的一种语言,因此它必须简单明了.Java语言的简单性主要体现在以下三个方面: 1) Java的风格类似于C++,因而C++程序员是非常熟悉的.从某 ...

  10. 关于服务器raid的一个记录

    今天下午,在装操作系统的时候,特意的测试了下raid1的性能. 1. 开启操作系统 直接正常开启操作系统,操作系统的硬盘做的是raid1,从而数据写俩份,从而在损坏一张盘之后,另外一张盘并不会收到影响 ...