[BZOJ1179][Apio2009]Atm

[BZOJ1179][Apio2009]Atm

试题描述

输入

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

输出

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

输入示例

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

输出示例

47

数据规模及约定

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

题解

强连通分量缩点再DP就行了。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <stack>
#include <vector>
#include <queue>
#include <cstdlib>
using namespace std;

const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *tail;
inline char Getchar() {
    if(Head == tail) {
        int l = fread(buffer, 1, BufferSize, stdin);
        tail = (Head = buffer) + l;
    }
    return *Head++;
}
int read() {
	int x = 0, f = 1; char c = Getchar();
	while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
	while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
	return x * f;
}

#define maxn 500010
#define maxm 500010
int n, m[3], S, head[3][maxn], next[3][maxm], to[3][maxm], val[maxn], f[maxn];
bool has[maxn], sh[maxn];

void AddEdge(int a, int b) {
	to[0][++m[0]] = b; next[0][m[0]] = head[0][a]; head[0][a] = m[0];
	swap(a, b);
	to[1][++m[1]] = b; next[1][m[1]] = head[1][a]; head[1][a] = m[1];
	return ;
}
void AddEdge2(int a, int b) {
	to[2][++m[2]] = b; next[2][m[2]] = head[2][a]; head[2][a] = m[2];
	return ;
}

int cnt, outs[maxn];
bool vis[maxn];
void dfs1(int u) {
	if(vis[u]) return ; vis[u] = 1;
	for(int e = head[0][u]; e; e = next[0][e]) if(!vis[to[0][e]]) dfs1(to[0][e]);
	outs[++cnt] = u;
	return ;
}
int scc, sccno[maxn], sccv[maxn];
void dfs2(int u) {
	if(vis[u]) return ; vis[u] = 1;
	sccno[u] = scc; sccv[scc] += val[u];
	for(int e = head[1][u]; e; e = next[1][e]) if(!vis[to[1][e]]) dfs2(to[1][e]);
	return ;
}

int main() {
	n = read(); int m = read();
	while(m--) {
		int a = read(), b = read();
		AddEdge(a, b);
	}
	for(int i = 1; i <= n; i++) val[i] = read();
	S = read();
	int cb = read(); for(int i = 1; i <= cb; i++) has[read()] = 1;
	
	for(int i = 1; i <= n; i++) dfs1(i);
	memset(vis, 0, sizeof(vis));
	for(int i = n; i; i--) scc++, dfs2(outs[i]);
	for(int i = 1; i <= n; i++) {
		for(int e = head[0][i]; e; e = next[0][e]) if(sccno[i] != sccno[to[0][e]])
			AddEdge2(sccno[i], sccno[to[0][e]]);
		sh[sccno[i]] |= has[i];
	}
	f[sccno[S]] = sccv[sccno[S]];
	for(int i = sccno[S]; i <= scc; i++)
		for(int e = head[2][i]; e; e = next[2][e]) f[to[2][e]] = max(f[to[2][e]], f[i] + sccv[to[2][e]]);
	
	int ans = 0;
	for(int i = sccno[S]; i <= scc; i++) if(sh[i]) ans = max(ans, f[i]);
	printf("%d\n", ans);
	
	return 0;
}

 

posted @ 2016-04-25 12:52  xjr01  阅读(215)  评论(0编辑  收藏  举报