Input

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

Output

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

Sample Input


Sample Output


Hint

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


  觉得这道题和某道noip题(买卖水晶球的题)比较像,这道题似乎不能双向spfa,但是可以先用Tarjan找到强联通分量,然后缩点,这样就是一个有向无环图,就可以进行spfa,在有酒吧的点找最大值。

Code

 /**
* bzoj
* Problem#1179
* Accepted
* Time:6280ms
* Memory:56800k
*/
#include<iostream>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<ctime>
#include<map>
#include<stack>
#include<set>
#include<queue>
#include<vector>
#ifndef WIN32
#define AUTO "%lld"
#else
#define AUTO "%I64d"
#endif
using namespace std;
typedef bool boolean;
#define inf 0xfffffff
#define smin(a, b) (a) = min((a), (b))
#define smax(a, b) (a) = max((a), (b))
template<typename T>
inline boolean readInteger(T& u) {
char x;
int aFlag = ;
while(!isdigit((x = getchar())) && x != '-' && x != -);
if(x == -) {
ungetc(x, stdin);
return false;
}
if(x == '-') {
aFlag = -;
x = getchar();
}
for(u = x - ''; isdigit((x = getchar())); u = u * + x - '');
u *= aFlag;
ungetc(x, stdin);
return true;
} ///map template starts
typedef class Edge{
public:
int end;
int next;
Edge(const int end = , const int next = ):end(end), next(next) { }
}Edge; typedef class MapManager{
public:
int ce;
int *h;
Edge *edge;
MapManager() { }
MapManager(int points, int limit):ce() {
h = new int[(const int)(points + )];
edge = new Edge[(const int)(limit + )];
memset(h, , sizeof(int) * (points + ));
}
inline void addEdge(int from, int end) {
edge[++ce] = Edge(end, h[from]);
h[from] = ce;
}
Edge& operator [] (int pos) {
return edge[pos];
}
}MapManager;
#define m_begin(g, i) (g).h[(i)]
///map template ends int n, m, s, p;
int* moneys;
MapManager g;
boolean *rest; inline void init() {
readInteger(n);
readInteger(m);
moneys = new int[(const int)(n + )];
rest = new boolean[(const int)(n + )];
g = MapManager(n, * m);
memset(rest, false, sizeof(boolean) * (n + ));
for(int i = , a, b; i <= m; i++) {
readInteger(a);
readInteger(b);
g.addEdge(a, b);
}
for(int i = ; i <= n; i++)
readInteger(moneys[i]);
readInteger(s);
readInteger(p);
for(int i = , a; i <= p; i++) {
readInteger(a);
rest[a] = true;
}
} int cnt = ;
boolean *visited, *instack;
int* visitID, *exitID;
int *belong;
stack<int> st; inline void getPart(int end) {
int x;
do {
x = st.top();
st.pop();
instack[x] = false;
if(x != end) {
moneys[end] += moneys[x];
rest[end] = rest[x] || rest[end];
}
belong[x] = end;
} while(x != end);
} void tarjan(int node) {
visited[node] = instack[node] = true;
st.push(node);
visitID[node] = exitID[node] = ++cnt;
for(int i = m_begin(g, node); i != ; i = g[i].next) {
int& e = g[i].end;
if(!visited[e]) {
tarjan(e);
smin(exitID[node], exitID[e]);
} else if(instack[e]) {
smin(exitID[node], visitID[e]);
}
}
if(visitID[node] == exitID[node]) getPart(node);
} MapManager ng;
inline void build() {
visited = new boolean[(const int)(n + )];
instack = new boolean[(const int)(n + )];
visitID = new int[(const int)(n + )];
exitID = new int[(const int)(n + )];
belong = new int[(const int)(n + )];
memset(visited, false, sizeof(boolean) * (n + ));
memset(instack, false, sizeof(boolean) * (n + ));
ng = MapManager(n, m);
tarjan(s);
for(int i = ; i <= n; i++) {
for(int j = m_begin(g, i); j != ; j = g[j].next) {
int& e = g[j].end;
if(belong[i] == belong[e]) continue;
ng.addEdge(belong[i], belong[e]);
}
}
delete[] instack;
delete[] visitID;
delete[] exitID;
} queue<int> que;
int *f;
inline void spfa() {
f = new int[(const int)(n + )];
memset(f, , sizeof(int) * (n + ));
memset(visited, false, sizeof(boolean) * (n + ));
que.push(belong[s]);
f[belong[s]] = moneys[belong[s]];
while(!que.empty()) {
int e = que.front();
que.pop();
visited[e] = false;
for(int i = m_begin(ng, e); i != ; i = ng[i].next) {
int eu = ng[i].end;
if(belong[eu] != eu || belong[eu] == belong[e]) continue;
if(f[eu] < f[e] + moneys[eu]) {
f[eu] = f[e] + moneys[eu];
if(!visited[eu]) {
que.push(eu);
visited[eu] = true;
}
}
}
}
} inline void solve() {
build();
spfa();
int res = ;
for(int i = ; i <= n; i++) {
if(belong[i] == i && rest[i]) {
smax(res, f[i]);
}
}
printf("%d", res);
} int main() {
init();
solve();
return ;
}

bzoj 1179 [APIO 2009]Atm(APIO水题) - Tarjan - spfa的更多相关文章

  1. [APIO 2009] Atm

    传送门:>Here< 题意:给出一个有向图(有环),每个点有点权.从点S出发,经过每个点Tot可以加上点权,点可以经过多次,然而点权不能重复加多次.先要求走到某个终点E时点权最大.先要求在 ...

  2. BZOJ 2761: [JLOI2011]不重复数字 水题

    2761: [JLOI2011]不重复数字 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2100  Solved: 809 题目连接 http:// ...

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

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

  4. BZOJ 1968: [Ahoi2005]COMMON 约数研究 水题

    1968: [Ahoi2005]COMMON 约数研究 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeO ...

  5. BZOJ 1303: [CQOI2009]中位数图 【水题】

    给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b.中位数是指把所有元素从小到大排列后,位于中间的数. Input 第一行为两个正整数n和b ,第二行为1~n 的排列. Out ...

  6. 【BZOJ 1179】[Apio2009]Atm

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] tarjan强连通缩点一下. 然后把缩点之后,每个点的钱的数累加起来. 然后从S出发 开始一边做bfs一遍做dp. 最后输出有酒吧的 ...

  7. 【GDOI2015】 水题 tarjan缩点

    这一题,我当年只会$60$分做法..... 我们考虑对原图跑一波边双,然后缩成一个森林. 对于森林中的每一棵树,我们钦定一个根. 令$siz[x]$表示以$x$为根的子树中,在原图中点的个数. 令当前 ...

  8. BZOJ 1179 Atm 题解

    BZOJ 1179 Atm 题解 SPFA Algorithm Tarjan Algorithm Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来 ...

  9. BZOJ USACO 银组 水题集锦

    最近刷银组刷得好欢快,好像都是水题,在这里吧他们都记录一下吧(都是水题大家一定是道道都虐的把= =)几道比较神奇的题到时再列出来单独讲一下吧= =(其实我会说是BZOJ蹦了无聊再来写的么 = =) [ ...

随机推荐

  1. 解决oracle12c安装报“[INS-30131]执行安装程序验证所需的初始设置失败(原因:无法访问临时位置)”方法

    安装过很多次oracle,顺顺利利的,今天在新机子上安装oracle12c client过程中竟然神奇的报出一个错误: 很明显的,已经很明确的给出了安装失败的原因:无法访问临时位置!实际上,在安装数据 ...

  2. docker使用Dockerfile搭建spark集群

    1.创建Dockerfile文件,内容如下 # 基础镜像,包括jdk FROM openjdk:8u131-jre-alpine #作者 LABEL maintainer "tony@163 ...

  3. LightOJ 1027 - A Dangerous Maze(求期望)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1027 题意:又一个迷宫,有n个门,每个门又一个值num,如果num>0 说明在n ...

  4. 滑雪---poj1088(动态规划+记忆化搜索)

    题目链接:http://poj.org/problem?id=1088 有两种方法 一是按数值大小进行排序,然后按从小到大进行dp即可: #include <iostream> #incl ...

  5. Python3学习之路~2.6 集合操作

    集合是一个无序的,不重复的数据组合,它的主要作用如下: 去重,把一个列表变成集合,就自动去重了 关系测试,测试两组数据之前的交集.差集.并集等关系 常用操作 >>> list1 = ...

  6. C和C++不容易发现的区别

    1.char指针指向字符串常量 当下面的代码写到.c文件中时,可以正常运行;而写到.cpp文件中就会报错:无法从“const char [6]”转换为“char *”. char * c = &quo ...

  7. Python一键安装全部依赖包

    requirements.txt用来记录项目所有的依赖包和版本号,只需要一个简单的pip命令就能完成. pip freeze >requirements.txt 然后就可以用 pip insta ...

  8. R-sampe & seq函数学习[转载]

    转自:https://blog.csdn.net/u012108367/article/details/69913280 https://blog.csdn.net/qq_33547243/artic ...

  9. Hive学习笔记:基础语法

    Hive基础语法 1.创建表 – 用户表 CREATE [EXTERNAL外部表] TABLE [IF NOT EXISTS 是否存在] HUserInfo ( userid int comment ...

  10. [ps] 灰度和通道基础知识

    灰度.灰度值.灰度图像 灰度:灰度使用黑色调来表示物体,即用黑色为基准色,不同饱和度的黑色来显示图像.每个灰度对象都具有从0%(白色)到100%(黑色)的亮度值.使用黑白或灰度扫描仪生成的图像通常以灰 ...