缩点+spfa最长路【bzoj】 1179: [Apio2009]Atm
【bzoj】 1179: [Apio2009]Atm
Description
Siruseri 城中的道路都是单向的。不同的道路由路口连接。按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机。令人奇怪的是,Siruseri 的酒吧也都设在路口,虽然并不是每个路口都设有酒吧。Banditji 计划实施 Siruseri 有史以来最惊天动地的 ATM 抢劫。他将从市中心 出发,沿着单向道路行驶,抢劫所有他
途径的 ATM 机,最终他将在一个酒吧庆 祝他的胜利。使用高超的黑客技术,他获知了每个 ATM 机中可以掠取的现金数额。他希 望你帮助他计算从市中心出发最后到达某个酒吧时最多能抢劫的现金总数。他可 以经过同一路口或道路任意多次。但只要他抢劫过某个 ATM 机后,该 ATM 机 里面就不会再有钱了。
Input
第一行包含两个整数N、M。N表示路口的个数,M表示道路条数。
接下来M行,每行两个整数,这两个整数都在1到N之间,
第i+1行的两个整数表示第i条道路的起点和终点的路口编号。
接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数。
接下来一行包含两个整数S、P,S表示市中心的编号,也就是出发的路口。P表示酒吧数目。
接下来的一行中有P个整数,表示P个有酒吧的路口的编号
N, M<=500000。每个ATM机中可取的钱数为一个非负整数且不超过4000。
输入数据保证你可以从市中心沿着Siruseri的单向的道路到达其中的至少一个酒吧。
Output
输出一个整数,表示Banditji从市中心开始到某个酒吧结束所能抢劫的最多的现金总数。
莫名其妙的自信自己可以一遍A,毕竟做过几乎一样的加强版(捂脸。。。)
先缩点,把强连通分量里的每一个点的权值全部赋给所之后的点,也就是belong[i]。
再对于缩完点之后的图,跑一个点权SPFA就可以了。
拓扑排序+DP的做法会更快,不过有待学习。
code:
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int wx=500017;
inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
return sum*f;
}
struct e{
int nxt,to,dis;
}edge[wx];
struct E{
int nxt,to;
}Edge[wx];
int n,m;
int num,Tot,top,tot,col;
int a[wx],A[wx],belong[wx],size[wx],dis[wx],vis[wx];
int head[wx],Head[wx],dfn[wx],low[wx],st[wx],flag[wx];
void add(int from,int to,int dis){
edge[++num].nxt=head[from];
edge[num].to=to;
edge[num].dis=dis;
head[from]=num;
}
void add(int from,int to){
Edge[++Tot].nxt=Head[from];
Edge[Tot].to=to;
Head[from]=Tot;
}
void Tarjan(int u){
dfn[u]=low[u]=++tot;
st[++top]=u;
for(int i=Head[u];i;i=Edge[i].nxt){
int v=Edge[i].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(dfn[u]==low[u]){
belong[u]=++col;
size[col]++;
A[col]+=a[u];
while(st[top]!=u){
belong[st[top]]=col;
size[col]++;
A[col]+=a[st[top]];
top--;
}
top--;
}
}
void CQ(){
for(int u=1;u<=n;u++){
for(int i=Head[u];i;i=Edge[i].nxt){
int v=Edge[i].to;
if(belong[u]!=belong[v]){
add(belong[u],belong[v],0);
}
}
}
}
queue<int > q;
void SPFA(int s){
for(int i=1;i<=col;i++)dis[i]=-1;
dis[s]=A[s];vis[s]=1;q.push(s);
while(q.size()){
int u=q.front();q.pop();
vis[u]=0;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(dis[v]<dis[u]+A[v]){
dis[v]=dis[u]+A[v];
if(!vis[v]){
vis[v]=1;q.push(v);
}
}
}
}
}
int main(){
n=read();m=read();
for(int i=1,x,y;i<=m;i++){
x=read();y=read();add(x,y);
}
for(int i=1;i<=n;i++)a[i]=read();
int s,p;s=read();p=read();
for(int i=1,x;i<=p;i++){
x=read();flag[i]=x;
}
for(int i=1;i<=n;i++){
if(!dfn[i])Tarjan(i);
}
CQ();
SPFA(belong[s]);
int ans=0;
for(int i=1;i<=p;i++){
ans=max(ans,dis[belong[flag[i]]]);
}
printf("%d\n",ans);
return 0;
}
缩点+spfa最长路【bzoj】 1179: [Apio2009]Atm的更多相关文章
- 【bzoj1179】[Apio2009]Atm Tarjan缩点+Spfa最长路
题目描述 输入 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每 ...
- Tarjan缩点+Spfa最长路【p3627】[APIO2009] 抢掠计划
Description Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机.令人奇怪的是,Siruseri ...
- bzoj 1179: [Apio2009]Atm【tarjan+spfa】
明明优化了spfa还是好慢-- 因为只能取一次值,所以先tarjan缩点,把一个scc的点权和加起来作为新点的点权,然后建立新图.在新图上跑spfa最长路,最后把酒吧点的dis取个max就是答案. # ...
- BZOJ 1179 [Apio2009]Atm(强连通分量)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1179 [题目大意] 给出一张有向带环点权图,给出一些终点,在路径中同一个点的点权只能累 ...
- BZOJ 1179: [Apio2009]Atm( tarjan + 最短路 )
对于一个强连通分量, 一定是整个走或者不走, 所以tarjan缩点然后跑dijkstra. ------------------------------------------------------ ...
- bzoj 1179 [Apio2009]Atm——SCC缩点+spfa
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1179 显然SCC缩点. 然后准备倒着拓扑序推到st,结果WA. 听TJ说dj求最长路会发生不 ...
- bzoj1179: [Apio2009]Atm 【缩点+spfa最长路】
题目传送门 Description Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruser i 银行的 ATM 取款机.令人奇怪的是,S ...
- [luogu3627 APIO2009] 抢掠计划 (tarjan缩点+spfa最长路)
传送门 Description Input 第一行包含两个整数 N.M.N 表示路口的个数,M 表示道路条数.接下来 M 行,每行两个整数,这两个整数都在 1 到 N 之间,第 i+1 行的两个整数表 ...
- bzoj 1179[Apio2009]Atm (tarjan+spfa)
题目 输入 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一 ...
随机推荐
- [置顶]
linux getline()函数
getline()函数是什么?百度百科这样解释: getline不是C库函数,而是C++库函数.它会生成一个包含一串从输入流读入的字符的字符串,直到以下情况发生会导致生成的此字符串结束.1) ...
- 应用HTMLTestRunner整合测试报告
为了便于测试脚本的维护,以及更多测试用例的管理,于是根据上次学习的HTMLTestRunner生成的测试报告,今天将对其进行整理.我们之前使用 TestSuite 只是在一个.py 文件里添加多个测试 ...
- CentOS 7.2 部署Rsync + Lsyncd服务实现文件实时同步/备份 (二)
发送端配置: 一.配置密钥 1. 主/从服务器之间启用基于密钥的身份验证.登录发送端服务器并用 " ssh-keygen " 命令生成公共或私有的密钥. 2. 使用 " ...
- 11-28 网页基础--JavaScript(DOM)
网页基础 第二部分--HTMLDOM操作 一.定义:htmlDOM是一种面向对象的树的模型,它包含html中的所有元素:通过html可以找到所有包含在dom中的元素. 二.作用: 1.查找html元素 ...
- CentOS6.5安装完没有网络的解决办法
昨天下了个CentOS 6.5 Minimal 版,在VMware 10下安装好了之后,发现上不了网,PING外网也PING不通. 在网上搜了一下,发现Linux安装好了之后,网卡默认是没有启动的,下 ...
- C++深度解析教程学习笔记(2)C++中的引用
1.C++中的引用 (1)变量名的回顾 ①变量是一段实际连续存储空间的别名,程序中通过变量来申请并命名存储空间 ②通过变量的名字可以使用存储空间.(变量的名字就是变量的值,&变量名是取地址操作 ...
- [Python Study Notes]气泡散点图绘制
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ...
- python中not的用法
python中的not具体表示是什么: 在python中not是逻辑判断词,用于布尔型True和False,not True为False,not False为True,以下是几个常用的not的用法: ...
- java输入输出--I/O操作基础知识学习
一.java的I/O流 1. 输入流(字节流和字符流,字节流操作的数据单元是8位的字节,字符流操作的是16位的字符)(InputStream 和Reader作为基类) 2.输出流(字节流和字符流,字节 ...
- 思考题-关于CSS(转)
dl, dt, dd三个标签浏览器默认margin值多少?是否有标签默认文字粗体? line-height:150%和line-height:1.5的区别是? float为何会让外部容器高度塌陷?这是 ...