Tarjan缩点+Spfa最长路【p3627】[APIO2009] 抢掠计划
Description
Siruseri 城中的道路都是单向的。不同的道路由路口连接。按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机。令人奇怪的是,Siruseri 的酒吧也都设在路口,虽然并不是每个路口都设有酒吧。
Banditji 计划实施 Siruseri 有史以来最惊天动地的 ATM 抢劫。他将从市中心 出发,沿着单向道路行驶,抢劫所有他途径的 ATM 机,最终他将在一个酒吧庆 祝他的胜利。
使用高超的黑客技术,他获知了每个 ATM 机中可以掠取的现金数额。他希 望你帮助他计算从市中心出发最后到达某个酒吧时最多能抢劫的现金总数。他可 以经过同一路口或道路任意多次。但只要他抢劫过某个 ATM 机后,该 ATM 机 里面就不会再有钱了。 例如,假设该城中有 6 个路口,道路的连接情况如下图所示:
市中心在路口 1,由一个入口符号→来标识,那些有酒吧的路口用双圈来表
示。每个 ATM 机中可取的钱数标在了路口的上方。在这个例子中,Banditji 能抢 劫的现金总数为 47,实施的抢劫路线是:1-2-4-1-2-3-5。
Input
第一行包含两个整数 N、M。N 表示路口的个数,M 表示道路条数。接下来 M 行,每行两个整数,这两个整数都在 1 到 N 之间,第 i+1 行的两个整数表示第 i 条道路的起点和终点的路口编号。接下来 N 行,每行一个整数,按顺序表示每 个路口处的 ATM 机中的钱数。接下来一行包含两个整数 S、P,S 表示市中心的 编号,也就是出发的路口。P 表示酒吧数目。接下来的一行中有 P 个整数,表示 P 个有酒吧的路口的编号。
Output
输出一个整数,表示 Banditji 从市中心开始到某个酒吧结束所能抢劫的最多 的现金总数。
\(Tarjan\)缩点跑最长路,
在求强联通分量的时候维护每个联通分量的\(val\)(即当前强联通分量中所有\(atm\)的钱数.
不能再次建边的时候再求.(会出锅,但是原理我不太知道。
再对强联通分量建边跑最长路即可.
注意:\(Dijkstra\)的贪心策略不可跑最长路。
这里数组可以重复使用,不过这题没有卡数组,就没有重复使用了 qwq.
代码
#include<cstdio>
#include<cctype>
#include<queue>
#define N 500008
#define R register
using namespace std;
inline void in(int &x)
{
int f=1;x=0;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s)){x=x*10+s-'0';s=getchar();}
x*=f;
}
int n,m,head[N],tot,low[N],dfn[N],col,belong[N],idx,stk[N],pos;
int val[N],v[N],h[N],ttt,p,t[N],dis[N],top,s,ans;
struct cod{int u,v;}edge[N<<2],e[N<<2];
bool inq[N],vis[N];
inline void add(int x,int y)
{
edge[++tot].u=head[x];
edge[tot].v=y;
head[x]=tot;
}
inline void ado(int x,int y)
{
e[++ttt].u=h[x];
e[ttt].v=y;
h[x]=ttt;
}
inline void spfa(int s)
{
for(R int i=1;i<=col;i++)dis[i]=-214748364;
queue<int>q;
q.push(s);vis[s]=true;dis[s]=val[s];
while(!q.empty())
{
int u=q.front();q.pop();vis[u]=false;
for(R int i=h[u];i;i=e[i].u)
{
if(dis[e[i].v]<dis[u]+val[e[i].v])
{
dis[e[i].v]=dis[u]+val[e[i].v];
if(!vis[e[i].v])
{
vis[e[i].v]=true;
q.push(e[i].v);
}
}
}
}
for(R int i=1;i<=p;i++)
ans=max(ans,dis[belong[t[i]]]);
printf("%d",ans);
}
void tarjan(int x)
{
dfn[x]=low[x]=++idx;
stk[++top]=x;inq[x]=true;
for(R int i=head[x];i;i=edge[i].u)
{
if(!dfn[edge[i].v])
{
tarjan(edge[i].v);
low[x]=min(low[x],low[edge[i].v]);
}
else if(inq[edge[i].v])
low[x]=min(low[x],dfn[edge[i].v]);
}
if(low[x]==dfn[x])
{
col++;
int now=-1;
while(now!=x)
{
now=stk[top--];
inq[now]=false;
belong[now]=col;
val[col]+=v[now];
}
}
}
int main()
{
in(n),in(m);
for(R int i=1,x,y;i<=m;i++)
{
in(x),in(y);
add(x,y);
}
for(R int i=1;i<=n;i++)in(v[i]);
for(R int i=1;i<=n;i++)
if(!dfn[i])tarjan(i);
for(R int i=1;i<=n;i++)
for(R int j=head[i];j;j=edge[j].u)
if(belong[edge[j].v]!=belong[i])
ado(belong[i],belong[edge[j].v]);
in(s);in(p);
for(R int i=1;i<=p;i++)in(t[i]);
spfa(belong[s]);
}
Tarjan缩点+Spfa最长路【p3627】[APIO2009] 抢掠计划的更多相关文章
- 【bzoj1179】[Apio2009]Atm Tarjan缩点+Spfa最长路
题目描述 输入 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每 ...
- [luogu3627 APIO2009] 抢掠计划 (tarjan缩点+spfa最长路)
传送门 Description Input 第一行包含两个整数 N.M.N 表示路口的个数,M 表示道路条数.接下来 M 行,每行两个整数,这两个整数都在 1 到 N 之间,第 i+1 行的两个整数表 ...
- P3627 [APIO2009]抢掠计划
P3627 [APIO2009]抢掠计划 Tarjan缩点+最短(最长)路 显然的缩点...... 在缩点时,顺便维护每个强连通分量的总权值 缩完点按照惯例建个新图 然后跑一遍spfa最长路,枚举每个 ...
- 洛谷 P3627 [APIO2009]抢掠计划 Tarjan缩点+Spfa求最长路
题目地址:https://www.luogu.com.cn/problem/P3627 第一次寒假训练的结测题,思路本身不难,但对于我这个码力蒟蒻来说实现难度不小-考试时肛了将近两个半小时才刚肛出来. ...
- bzoj1179: [Apio2009]Atm 【缩点+spfa最长路】
题目传送门 Description Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruser i 银行的 ATM 取款机.令人奇怪的是,S ...
- Grouping ZOJ - 3795 (tarjan缩点求最长路)
题目链接:https://cn.vjudge.net/problem/ZOJ-3795 题目大意:给你n个人,m个关系, 让你对这个n个人进行分组,要求:尽可能的分组最少,然后每个组里面的人都没有关系 ...
- BZOJ5450: 轰炸(水题,Tarjan缩点求最长路)
5450: 轰炸 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 43 Solved:18[Submit][Status][Discuss] Desc ...
- BZOJ1093 [ZJOI2007]最大半连通子图 【tarjan缩点 + DAG最长路计数】
题目 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意 两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G ...
- 缩点+spfa最长路【bzoj】 1179: [Apio2009]Atm
[bzoj] 1179: [Apio2009]Atm Description Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruseri ...
随机推荐
- 常见算法用Pascal实现
基本算法 这些都是非常基本的的算法,希望所有学习的人都能理解! 1.数论算法 求两数的最大公约数 function gcd(a,b:integer):integ ...
- XSS注入常用语句积累
<script>alert('hello,gaga!');</script> //经典语句,哈哈! >"'><img src="javas ...
- linux下如何修改进程优先级?
linux下的进程调度优先级是从-20到19,一共40个级别,数字越大,表示进程的优先级越低.默认时候,进程的优先级是0.查看进程优先级有两个办法:ps和top. 改变进程的优先级的方法有两种: 1, ...
- BZOJ4031 [HEOI2015]小Z的房间 【矩阵树定理 + 高斯消元】
题目链接 BZOJ4031 题解 第一眼:这不裸的矩阵树定理么 第二眼:这个模\(10^9\)是什么鬼嘛QAQ 想尝试递归求行列式,发现这是\(O(n!)\)的.. 想上高斯消元,却又处理不了逆元这个 ...
- 朗格拉日计数(counter)
朗格拉日计数(counter) 题目描述 在平面上以圆周等分排列着n个带标号(标号为1-n)的点,你需要计算有多少个三元组(a,b,c),满足a<b<c而且标号为a,b,c的点在圆上分布的 ...
- CF888E Maximum Subsequence (Meet in the middle,贪心)
题目链接 Solution Meet in the middle. 考虑到 \(2^{35}\) 枚举会超时,于是分成两半枚举(尽量平均). 然后不能 \(n^2\) 去匹配,需要用到一点贪心: 将数 ...
- mac平台打造犀利的Android Studio开发环境
0x0 背景介绍 随着Android Studio功能越来越强大,Android平台的开发者们基本上都从原来的Eclipse + ADT 转到了AS上.本文就记录自己在配置AS环境过程中遇到的各种问 ...
- mysql索引记
如果字段是数值型,where 是字符串型,走索引但是,如果字段是字符串型,但是where 是数值型,不走索引
- 快速了解Android重要机制
转自 http://www.jianshu.com/p/5f6d79323923 一.Android系统底层研究 关于底层的知识点不是在一篇文章中能讲解清楚,参见本人的Android底层研究系列,不断 ...
- jsp的九大内置对象及EL表达式的隐含对象
九大内置对象: request request对象具有请求域,即完成客户端的请求之前,该对象一直有效. response response对象具有页面作用域,即访问一个页面 ...