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. dockerfile学习笔记

    Dockfile 参考资料:http://www.cnblogs.com/CloudMan6/p/6864000.html http://www.cnblogs.com/CloudMan6/p/687 ...

  2. count(*) count(1) count(column)区别

    count(*) 和count(1)的效果是一样的.在某些情况下效率不一样.也会统计包含null的记录. count(column)会返回当前字段不为null的记录数.

  3. SQL Server 登录名、服务器角色、用户名和数据库角色 --- 解释

    一.基本解释 登录名:登录服务器的用户账号: 服务器角色:登录名对该服务器具有的权限,角色分多种的,一个角色可以有多个登录名,如操作系统的系统用户可以有多个. SQL服务器角色  sysadmin   ...

  4. Ubuntu Kylin 14.04 安装配置 jdk、eclipse、tomcat 通用

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/qq1053781225/article/details/24810107 一.安装jdk       ...

  5. CentOS工作内容(二)关闭SELinux

    CentOS工作内容(二)关闭SELinux CentOS安装完成后,有很多配置要改,不过最重要就是关闭SELinux SELinux是增强安全性的一项功能,不是SELinux不好,而是当功能安全性较 ...

  6. 后缀名htm与html的区别

    前者是超文本标记(Hypertext Markup) 后者是超文本标记语言(Hypertext Markup Language) 可以说 htm = html 同时,这两种都是静态网页文件的扩展名,扩 ...

  7. union 类型(即sum types)在golang语言中的实现

    http://www.jerf.org/iri/post/2917 Sum Types in Go posted Jun 02, 2013 in Programming, Golang, Haskel ...

  8. 搭建基于HTTP协议内网yum仓库

    目录 1. 前言 2. 把rpm包下载到本地 3. 配置nginx对外提供服务 4. 配置本地repo文件 5. 生成repodata信息 6. 检查及使用 7. 对管理机器上的仓库进行更新 参考资料 ...

  9. tf.nn.embedding_lookup函数的用法

    关于np.random.RandomState.np.random.rand.np.random.random.np.random_sample参考https://blog.csdn.net/lanc ...

  10. [LeetCode] 64. Minimum Path Sum_Medium tag: Dynamic Programming

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...