首页 > 代码库 > 【BZOJ】1179: [Apio2009]Atm(tarjan+spfa)

【BZOJ】1179: [Apio2009]Atm(tarjan+spfa)

http://www.lydsy.com/JudgeOnline/problem.php?id=1179

缩点建图。。。

#include <cstdio>#include <cstring>#include <cmath>#include <string>#include <iostream>#include <algorithm>#include <queue>#include <set>#include <map>using namespace std;typedef long long ll;#define rep(i, n) for(int i=0; i<(n); ++i)#define for1(i,a,n) for(int i=(a);i<=(n);++i)#define for2(i,a,n) for(int i=(a);i<(n);++i)#define for3(i,a,n) for(int i=(a);i>=(n);--i)#define for4(i,a,n) for(int i=(a);i>(n);--i)#define CC(i,a) memset(i,a,sizeof(i))#define read(a) a=getint()#define print(a) printf("%d", a)#define dbg(x) cout << (#x) << " = " << (x) << endl#define error(x) (!(x)?puts("error"):0)#define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<‘0‘||c>‘9‘; c=getchar()) if(c==‘-‘) k=-1; for(; c>=‘0‘&&c<=‘9‘; c=getchar()) r=r*10+c-‘0‘; return k*r; }const int N=1000005, oo=~0u>>1;int FF[N], LL[N], scc, p[N], vis[N], s[N], top, tot, d[N];struct GR {	int ihead[N], cnt, n, w[N];	struct dat { int to, next; }e[N];	void add(int u, int v) {		e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v;	}	void tarjan(int x) {		FF[x]=LL[x]=++tot; vis[x]=1; s[++top]=x;		int y;		rdm(x, i) {			y=e[i].to;			if(!FF[y]) tarjan(y), LL[x]=min(LL[x], LL[y]);			else if(vis[y]) LL[x]=min(LL[x], FF[y]);		}		if(LL[x]==FF[x]) {			++scc;			do {				y=s[top--];				vis[y]=0;				p[y]=scc;			} while(x!=y);		}	}	void tarjan() { for1(i, 1, n) if(!FF[i]) tarjan(i); }	void spfa(int x) {		for1(i, 1, n) d[i]=-oo, vis[i]=0;		d[x]=w[x]; vis[x]=1;		int front, tail; front=tail=0;		int *q=s;		q[tail++]=x;		while(front!=tail) {			int u=q[front++], v; if(front==N) front=0; vis[u]=0;			rdm(u, i) if(d[e[i].to]<d[u]+w[e[i].to]) {				v=e[i].to;				d[v]=d[u]+w[v];				if(!vis[v]) {					vis[v]=1;					if(d[q[front]]<d[v]) {						--front; if(front<0) front+=N;						q[front]=v;					}					else {						q[tail++]=v; if(tail==N) tail=0;					}				}			}		}	}}G, g;void build() {	G.tarjan();	g.n=scc;	for1(i, 1, G.n) g.w[p[i]]+=G.w[i];	for1(x, 1, G.n) for(int i=G.ihead[x]; i; i=G.e[i].next) if(p[x]!=p[G.e[i].to]) g.add(p[x], p[G.e[i].to]);}int n, m, ans, num, bar[N];int main() {	read(n); read(m); G.n=n;	for1(i, 1, m) { int u=getint(), v=getint(); G.add(u, v); }	for1(i, 1, n) read(G.w[i]);	int s=getint(); read(num);	build();	g.spfa(p[s]);	for1(i, 1, num) read(bar[i]);	for1(i, 1, num) ans=max(ans, d[p[bar[i]]]);	printf("%d\n", ans);	return 0;}

  

 


 

 

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

 

Source

【BZOJ】1179: [Apio2009]Atm(tarjan+spfa)