1179: [Apio2009]Atm

Description

Input

第一行包含两个整数N、M。N表示路口的个数,M表示道路条数。接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号。接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数。接下来一行包含两个整数S、P,S表示市中心的编号,也就是出发的路口。P表示酒吧数目。接下来的一行中有P个整数,表示P个有酒吧的路口的编号

Output

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

Sample Input

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

Sample Output

47

HINT

50%的输入保证N, M<=3000。所有的输入保证N, M<=500000。每个ATM机中可取的钱数为一个非负整数且不超过4000。输入数据保证你可以从市中心沿着Siruseri的单向的道路到达其中的至少一个酒吧。

分析:

这道题其实很迷。首先这道题发现如果在一个强连通分量里面,都可以走到,而且也没有限制走的次数,所以我们可以将在强连通分量里面的点,缩成一个全新的点。之后造出来一个全新的图。boom!新造出来的图可以走一遍最短路spfa。就好了。

至于怎么缩点。
用并查集先找到父亲与儿子。之后每次判断出一个强量通分量就用将他们的父亲全连成第一个数。
之后在新建图(如果一个点的父亲与儿子的父亲不相同,那他们1,连上2,建边)
这个边其实可以重复利用。这样可以节省空间。

#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
struct node{
int infont,v,next,val;
}edge[1000010];
int strack[1000010],cnt,father[1000000],heads[500010],d[500010],s,p;
int DFN[1000000],LOW[1000000],bar[1000000],visit[1000010],du[500010];
int n,m,index_1,head;
void address(int x,int y){
edge[++cnt].infont=x;
edge[cnt].v=y;
edge[cnt].next=heads[x];
heads[x]=cnt;
return ;
}
void tarjan(int x){
LOW[x]=DFN[x]=++index_1;
visit[x]=1;
strack[++head]=x;
for(int i=heads[x];i!=-1;i=edge[i].next){
if(!DFN[edge[i].v]){
tarjan(edge[i].v);
LOW[x]=min(LOW[x],LOW[edge[i].v]);
}
else if(visit[edge[i].v]){
LOW[x]=min(LOW[x],DFN[edge[i].v]);
}
}
if(LOW[x]==DFN[x])
{
while(strack[head]!=x){
visit[strack[head]]=0;
d[x]+=d[strack[head]];
father[strack[head]]=x;
head--;
}
head--;
visit[x]=0;
}
return ;
}
void build(){
memset(heads,-1,sizeof(heads));
cnt=0;
for(int i=1;i<=m;++i)
{
if(father[edge[i].infont]!=father[edge[i].v])
address(father[edge[i].infont],father[edge[i].v]);
}
return ;
}
void SPFA(int x)
{
memset(visit,0,sizeof(visit));
memset(strack,0,sizeof(strack));
memset(du,-0x3f,sizeof(du));
int last;
last=head=1;
strack[head]=x;
visit[x]=1;
du[x]=d[x];
while(head<=last){
int news=strack[head];
for(int i=heads[news];i!=-1;i=edge[i].next)
{
if(du[edge[i].v]<du[news]+d[edge[i].v])
{
du[edge[i].v]=du[news]+d[edge[i].v];
if(visit[edge[i].v])continue;
visit[edge[i].v]=1;
strack[++last]=edge[i].v;
}
}
head++;
visit[news]=0;
}
return ;
}
int main( ){
memset(heads,-1,sizeof(heads));
scanf("%d%d",&n,&m);
int a,b;
for(int i=1;i<=m;++i){
scanf("%d%d",&a,&b);
address(a,b);
}
for(int i=1;i<=n;++i){
scanf("%d",&a);
d[i]=a;
father[i]=i;
}
for(int i=1;i<=n;++i)if(!DFN[i])tarjan(i);
build();
scanf("%d%d",&a,&b);
SPFA(father[a]);
int ans=0;
for(int i=1;i<=b;++i)
{
scanf("%d",&a);
ans=max(ans,du[father[a]]);
}
printf("%d",ans);
return 0;
}

BZOJ1179 Atm //缩点+spfa的更多相关文章

  1. BZOJ1179 : [Apio2009]Atm 缩点+spfa

    1179: [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 2069  Solved: 826[Submit][Status ...

  2. 【bzoj1179】[Apio2009]Atm Tarjan缩点+Spfa最长路

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

  3. bzoj1179 Atm

    Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口 ...

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

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

  5. bzoj1179: [Apio2009]Atm 【缩点+spfa最长路】

    题目传送门 Description Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruser i 银行的 ATM 取款机.令人奇怪的是,S ...

  6. 【BZOJ1179】 [Apio2009]Atm tarjan缩点+SPFA

    Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口 ...

  7. [BZOJ1179] [Apio2009]Atm(tarjan缩点 + spfa)

    传送门 题意 N个点M条边的有向图 每个点有点权 从某一个结点出发 问能获得的最大点权和 一个点的点权最多被计算一次 N<=500000 M<=500000 思路 先tarjan缩点,然后 ...

  8. [APIO2009]抢掠计划 tarjan缩点+spfa BZOJ1179

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

  9. 缩点+spfa最长路【bzoj】 1179: [Apio2009]Atm

    [bzoj] 1179: [Apio2009]Atm Description Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruseri ...

随机推荐

  1. 手把手教你做一个原生js拖动滑块【兼容PC和移动端】

    废话少说: 在PC端可以用mousedown来触发一个滑块滑动的效果,但在手机上,貌似无法识别这个事件,但手机上有touchstart事件,可以通过一系列"touch"事件来替代P ...

  2. 大叔也说Xamarin~Android篇~原生登陆与WebView的网站如何共享Session

    回到目录 事情是这样的,我们最近开了一个APP,主要使用xamarin做了一个登陆,它与服务器API进行数据通讯,当用户名密码正确去,跳转到新的activity,并在webview控件中打开服务端的H ...

  3. php做登录注册页面及加载

    //SQL注入攻击 //1.过滤用户的输入 //2.使用预处理语句 //3.写代码的时候尽量避免 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1. ...

  4. Android开发学习之路-GSON使用心得(OCR图片识别)

    在安卓中解析JSON串可以使用的方法有很多,比如说用官方提供的JSONObject或者谷歌提供的开源库GSON,以及一些第三方开源库. 这里用的是GSON,为了测试方便,借助了一个百度的api,一个图 ...

  5. Node.js入门:文件查找机制

    文件查找流程图 从文件模块缓存中加载     尽管原生模块与文件模块的优先级不同,但是都不会优先于从文件模块的缓存中加载已经存在的模块. 从原生模块加载     原生模块的优先级仅次于文件模块缓存的优 ...

  6. lua随机数的问题

    在看 lua 的 math.random 函数的时候发现一个问题,就是在没有重新设置随机种子的时候, random 返回的前几个随机数并不是那么特别随机,尤其当随机范围很小的时候,比如 100 左右的 ...

  7. Atitit 面向对象弊端与问题 坏处 缺点

    Atitit 面向对象弊端与问题 坏处 缺点   1.1. 状态fsm,反模块化,又是反并行的,这是它的非常固有的特征, 1 1.2. 现时的OOP编程有可能不缓存友好(cache friendly) ...

  8. fir.im Weekly - iOS/Android 应用程序架构解析

    假如问你一个iOS or Android app的架构,你会从哪些方面来说呢? 本期 fir.im Weekly 收集了关于  iOS/Android 开发资源,也加入了一些关于 Web 前端方面的分 ...

  9. Java override 和 overload 的区别

    override 是重写(覆盖)了一个方法,用来实现不同的功能,一般是用于子类继承父类时,重写父类的方法的时候. 重写(覆盖)的规则: 1.重写方法的参数列表必须表示与被重写的方法相同,否则不能称为重 ...

  10. mvc 权限设计

    1.http://blog.csdn.net/vera514514/article/details/8285154 2.http://www.cnblogs.com/cmsdn/p/3433995.h ...