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

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的更多相关文章
- [APIO 2009] Atm
传送门:>Here< 题意:给出一个有向图(有环),每个点有点权.从点S出发,经过每个点Tot可以加上点权,点可以经过多次,然而点权不能重复加多次.先要求走到某个终点E时点权最大.先要求在 ...
- BZOJ 2761: [JLOI2011]不重复数字 水题
2761: [JLOI2011]不重复数字 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2100 Solved: 809 题目连接 http:// ...
- BZOJ 1179 抢掠计划atm (缩点+有向无环图DP)
手动博客搬家: 本文发表于20170716 10:58:18, 原地址https://blog.csdn.net/suncongbo/article/details/81061601 https:// ...
- BZOJ 1968: [Ahoi2005]COMMON 约数研究 水题
1968: [Ahoi2005]COMMON 约数研究 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeO ...
- BZOJ 1303: [CQOI2009]中位数图 【水题】
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b.中位数是指把所有元素从小到大排列后,位于中间的数. Input 第一行为两个正整数n和b ,第二行为1~n 的排列. Out ...
- 【BZOJ 1179】[Apio2009]Atm
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] tarjan强连通缩点一下. 然后把缩点之后,每个点的钱的数累加起来. 然后从S出发 开始一边做bfs一遍做dp. 最后输出有酒吧的 ...
- 【GDOI2015】 水题 tarjan缩点
这一题,我当年只会$60$分做法..... 我们考虑对原图跑一波边双,然后缩成一个森林. 对于森林中的每一棵树,我们钦定一个根. 令$siz[x]$表示以$x$为根的子树中,在原图中点的个数. 令当前 ...
- BZOJ 1179 Atm 题解
BZOJ 1179 Atm 题解 SPFA Algorithm Tarjan Algorithm Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来 ...
- BZOJ USACO 银组 水题集锦
最近刷银组刷得好欢快,好像都是水题,在这里吧他们都记录一下吧(都是水题大家一定是道道都虐的把= =)几道比较神奇的题到时再列出来单独讲一下吧= =(其实我会说是BZOJ蹦了无聊再来写的么 = =) [ ...
随机推荐
- Drip is a launcher for the Java Virtual Machine that provides much faster startup times than the java command. The drip script is intended to be a drop-in replacement for the java command, only faster
小结: 1.初始化jvm: 2.第一次唤醒java命令不快,后续快: https://github.com/elastic/logstash Advanced: Drip Launcher Drip ...
- bin/hdfs namenode -format 格式化失败
确认配置正确前提下,将name目录删除重建,再格式化: hadoop防止将已经存在的集群格式化
- 万恶之源 - Python初识函数
什么是函数 我们目前为止,已经可以完成一些软件的基本功能了,那么我们来完成这样一个功能:约x pint("拿出手机") print("打开陌陌") print( ...
- POJ:Dungeon Master(三维bfs模板题)
Dungeon Master Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16748 Accepted: 6522 D ...
- ID和Name
ID和Name都可以用来标识一个标记,Javascript分别有两个方法getElementById和getElementByName来定位Dom节点. 区别如下: 1.我们知道在网页做Post提交时 ...
- [LeetCode] 733. Flood Fill_Easy tag: BFS
An image is represented by a 2-D array of integers, each integer representing the pixel value of the ...
- Winsock网络编程
Winsock是Windows下网络编程的标准接口.使用Winsock编程的步骤一般是比较固定的. 首先要包含头文件#include <WinSock2.h>,同时要添加WS2_32.li ...
- Postman接口自动化--Postman Script脚本功能使用详解
Postman Script 功能,支持原生的JS,所以可以使用JS解决很多接口自动化的一些问题,例如接口依赖.接口参数专递和接口断言等: 这里主要是针对Pre-Request Script 和 Te ...
- ambari集成impala
1.查看hdp版本,可在ambari-agent节点上查看 VERSION=`hdp-select status hadoop-client | sed 's/hadoop-client - \([0 ...
- 圆锥体完全均衡下重力异常正演 [MATLAB]
在完全均衡的模型下,若地表有一圆锥体(山峰等),计算跨越山顶的截面上所得到的各种重力异常. 地壳密度 $kg\cdot m^{-3}$ 上地幔密度 $g\cdot cm^{-3}$ 地表地形圆锥体半径 ...