BZOJ 1179 Atm 题解

SPFA Algorithm

Tarjan Algorithm

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的单向的道路到达其中的至少一个酒吧。

————————————————————————————分割线————————————————————————————

思路:

先用Tarjan算法求出途中的所有强连通分量,再讲每个分量值加和为点,再用SPFA算法求出以S为源点,最大价值的路径。

代码如下,(不是我的代码)

 //Code By にしきのまき

 #include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
struct node
{
int v;
int next;
};
int n,m;
node e[],map[];//邻接表存图
int st[],head[],cnt;
int atm[],money[];
int d[],q[];//最短路径&SPFA要用的队列
void build(int a,int b)
{
e[++cnt].v=b;
e[cnt].next=st[a];
st[a]=cnt;
}//建图找强连通分量
int stack[],top;//tarjan需要的栈
int dfn[],low[],dex;//时间戳(深搜序)、可回溯到的最早栈中时间戳、次序编号
bool vis[];//tarjan时判断点是否在栈中,SPFA时判断点是否在队列中
int color[],num;//表示同一强连通分量上的点
void tarjan(int x)//tarjan找强连通分量
{
dfn[x]=++dex;
low[x]=dex;
vis[x]=true;
stack[++top]=x;//当前点入栈
int i;
for(i=st[x];i!=;i=e[i].next)//枚举以当前点为起点的边
{
int temp=e[i].v;//temp为当前被枚举边的终点
if(!dfn[temp])//如果当前边终点未被处理
{
tarjan(temp);
low[x]=min(low[x],low[temp]);
}
else if(vis[temp])low[x]=min(low[x],dfn[temp]);
}
if(dfn[x]==low[x])
{
vis[x]=false;
color[x]=++num;//标记当前强连通分量内的点
while(stack[top]!=x)//栈顶元素依次出栈
{
color[stack[top]]=num;
vis[stack[top--]]=false;
}
top--;
}
}
void add()// 把同一强连通分量上的点缩成一个点,把这些点连成一张新图
{
cnt=;
int i,j;
for(i=;i<=n;i++)
{
for(j=st[i];j!=;j=e[j].next)
{
int temp=e[j].v;
if(color[i]!=color[temp])
{
map[++cnt].v=color[temp];
map[cnt].next=head[color[i]];
head[color[i]]=cnt;
}
} }
}
void spfa(int x)//SPFA找最长路
{
memset(vis,false,sizeof(vis));
int l=,r=;
q[l]=x;//初始点放入队列
vis[x]=true;
d[x]=money[x];
while(l<=r)
{
int u=q[l++];
for(int i=head[u];i!=;i=map[i].next)//遍历所有以当前点为起点的边
{
int v=map[i].v;
if(d[v]<d[u]+money[v])
{
d[v]=d[u]+money[v];
if(vis[v])continue;
q[++r]=v;//如果当前拓展的边的终点不在队列里,就把它放入队尾
vis[v]=true;
}
}
vis[u]=false;
}
}
int main()
{
int a,b,i,s,p,o,ans=;
scanf("%d%d",&n,&m);
for(i=;i<=m;i++)
{
scanf("%d%d",&a,&b);
build(a,b);
}//建初始图
for(i=;i<=n;i++)
{
if(!dfn[i])tarjan(i);//找强连通分量
}
add();//建新图
for(i=;i<=n;i++)
{
scanf("%d",&atm[i]);
money[color[i]]+=atm[i];
}
scanf("%d%d",&s,&p);
spfa(color[s]);//找单源最短路
for(i=;i<=p;i++)
{
scanf("%d",&o);
ans=max(ans,d[color[o]]);//找到以酒吧为终点的最长路
}
printf("%d",ans);
return ;
}

2016-09-14 20:00:54

(完)

BZOJ 1179 Atm 题解的更多相关文章

  1. bzoj 1179 Atm

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1179 题解: 一道比较综合的图论题 直接讲正解: 如果这个图G中存在某个强连通分量,那么这 ...

  2. BZOJ 1179 Atm(强连通分量缩点+DP)

    题目说可以通过一条边多次,且点权是非负的,所以如果走到图中的一个强连通分量,那么一定可以拿完这个强连通分量上的money. 所以缩点已经很明显了.缩完点之后图就是一个DAG,对于DAG可以用DP来求出 ...

  3. bzoj 1179 [APIO 2009]Atm(APIO水题) - Tarjan - spfa

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

  4. BZOJ 1179 [Apio2009]Atm(强连通分量)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1179 [题目大意] 给出一张有向带环点权图,给出一些终点,在路径中同一个点的点权只能累 ...

  5. BZOJ 1179: [Apio2009]Atm( tarjan + 最短路 )

    对于一个强连通分量, 一定是整个走或者不走, 所以tarjan缩点然后跑dijkstra. ------------------------------------------------------ ...

  6. bzoj 1179 [Apio2009]Atm 缩点+最短路

    [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 4290  Solved: 1893[Submit][Status][Dis ...

  7. BZOJ 1179 抢掠计划atm (缩点+有向无环图DP)

    手动博客搬家: 本文发表于20170716 10:58:18, 原地址https://blog.csdn.net/suncongbo/article/details/81061601 https:// ...

  8. bzoj 1179[Apio2009]Atm (tarjan+spfa)

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

  9. bzoj 1179: [Apio2009]Atm

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

随机推荐

  1. 设计模式学习之中介者模式(Mediator,行为型模式)(18)

    转载地址:http://www.cnblogs.com/zhili/p/MediatorPattern.html 一.引言 在现实生活中,有很多中介者模式的身影,例如QQ游戏平台,聊天室.QQ群和短信 ...

  2. linux命令**50

    1.ls命令 命令格式: ls [选项] [目录名] 命令功能: 列出目标目录中所有的子目录和文件. 常用参数: -a,列出所有文件包括隐藏文件 -l,列出详细信息,文件大小一般以字节大小显示 -h, ...

  3. 攻城狮在路上(贰) Spring(二)--- Spring IoC概念介绍

    一.IoC的概念: IoC(控制反转)是Spring容器的核心.另一种解释是DI(依赖注入),即让调用类对某一个接口的依赖关系由第三方注入,以移除调用类对某一个接口实现类的一览. 定义如此,由此可见, ...

  4. redmine安装部署

    http://www.sxt.cn/u/4647/blog/5557 http://blog.chinaunix.net/uid-26729093-id-4669508.html http://my. ...

  5. Win10 for Phone 裁剪保存

    //StorageFolder savedPics = ApplicationData.Current.LocalFolder; //BitmapImage bi = new BitmapImage( ...

  6. mysql 方法row_number()方法

    1.  SELECT  t.*,        @curRow := @curRow + 1 AS row_numberFROM    structure tJOIN    (SELECT @curR ...

  7. POJ 3140 Contestants Division 树形DP

    Contestants Division   Description In the new ACM-ICPC Regional Contest, a special monitoring and su ...

  8. input按钮上传按钮样式

    主要是定位和不透明度来实现: <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  9. JavaScript模拟函数重载

    JavaScript是没有函数重载的,但是我们可以通过其他方法来模拟函数重载,如下所示: <!DOCTYPE html> <html> <head> <met ...

  10. java运行jar命令提示没有主清单属性

    转自:http://jingyan.baidu.com/article/db55b60990f6084ba30a2fb8.html 可运行的jar:http://mushiqianmeng.blog. ...