[Apio2009][BZOJ1179] Atm
1179: [Apio2009]Atm
Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 1907 Solved: 756
[Submit][Status][Discuss]
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
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的单向的道路到达其中的至少一个酒吧。
tarjan缩点后SPFA秒。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<vector> #include<map> #define MAXN 500005 #define MOD 500005 using namespace std; int n,x,y,s,p,cnt,ans,sum,top,m,m0,m1,q[MAXN],dis[MAXN],belong[MAXN],patm[MAXN],atm[MAXN],next[MAXN],next0[MAXN],head[MAXN],head0[MAXN],list[MAXN],list0[MAXN],dfn[MAXN],low[MAXN],stack[MAXN],inset[MAXN]; bool v[MAXN]; int read() { char c=getchar(); int a=0; while (c<'0'||c>'9') c=getchar(); while (c>='0'&&c<='9') { a=a*10+c-'0'; c=getchar(); } return a; } void insert(int x,int y) { next[++m1]=head[x]; head[x]=m1; list[m1]=y; } void insert0(int x,int y) { next0[++m0]=head0[x]; head0[x]=m0; list0[m0]=y; } void dfs(int x) { dfn[x]=low[x]=++sum; stack[++top]=x; inset[x]=1; for (int y=head[x];y;y=next[y]) { if (!dfn[list[y]]) { dfs(list[y]); low[x]=min(low[list[y]],low[x]); } if (inset[list[y]]&&dfn[list[y]]<low[x]) low[x]=dfn[list[y]]; } int y=-1; if (dfn[x]==low[x]) { cnt++; while (y!=x) { y=stack[top--]; inset[y]=0; belong[y]=cnt; atm[cnt]+=patm[y]; } } } void tarjan() { for (int i=1;i<=n;i++) if (!dfn[i]) dfs(i); } void rebuild() { int y; for (int i=1;i<=n;i++) for (int y=head[i];y;y=next[y]) if (belong[i]!=belong[list[y]]) insert0(belong[i],belong[list[y]]); } void spfa() { int t=0,w=1; q[1]=s; memset(v,0,sizeof(v)); v[s]=1; memset(dis,0xff,sizeof(dis)); dis[s]=atm[s]; while (t!=w) { t=(t+1)%MOD; x=q[t]; for (int y=head0[x];y;y=next0[y]) if (dis[x]+atm[list0[y]]>dis[list0[y]]) { dis[list0[y]]=dis[x]+atm[list0[y]]; if (!v[list0[y]]) { v[list0[y]]=1; w=(w+1)%MOD; q[w]=list0[y]; } } v[x]=0; } } int main() { n=read(); m=read(); for (int i=1;i<=m;i++) { x=read(); y=read(); insert(x,y); } for (int i=1;i<=n;i++) patm[i]=read(); s=read(); p=read(); tarjan(); rebuild(); s=belong[s]; spfa(); for (int i=1;i<=p;i++) { x=read(); ans=max(ans,dis[belong[x]]); } printf("%d",ans); return 0; }