bzoj1179 Atm

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

 

缩点+spfa最大路

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<set>
using namespace std;
const int maxn=5e5+10,INF=2e9+5;
int n,m,S,v[maxn],ans;
set<int> G;
set<int>::iterator it;
 
int aa;char cc;
int read() {
    aa=0;cc=getchar();
    while(cc<'0'||cc>'9') cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    return aa;
}
 
int fir[maxn],nxt[maxn],to[maxn],e=0;
void add(int x,int y) {
    to[++e]=y;nxt[e]=fir[x];fir[x]=e;
}
 
int id[maxn],top[maxn],zz[maxn],d=0,tf=0;
int xd[maxn],sum[maxn],tot;
bool vis[maxn],inz[maxn];
void tj(int pos) {
    id[pos]=top[pos]=++d;zz[++tf]=pos;
    vis[pos]=inz[pos]=1;
    for(int y=fir[pos];y;y=nxt[y]) {
        if(vis[to[y]]) {
            if(inz[to[y]]) top[pos]=min(top[pos],top[to[y]]);
            continue;
        }
        tj(to[y]);top[pos]=min(top[pos],top[to[y]]);
    }
    if(top[pos]==id[pos]) {
        sum[++tot]=0;
        while(tf) {
            sum[tot]+=v[zz[tf]];
            xd[zz[tf]]=tot;
            inz[zz[tf]]=0;
            tf--;
            if(zz[tf+1]==pos) break;
        }
    }
}
 
int ff[maxn],nn[maxn],tt[maxn],ee=0;
void bld(int x,int y) {
    tt[++ee]=y;nn[ee]=ff[x];ff[x]=ee;
}
 
int dis[maxn];
void spfa(int st) {
    memset(zz,0,sizeof(zz));
    memset(vis,0,sizeof(vis));
    int s=1,t=0,x,y,z;
    zz[++t]=st;vis[st]=1;
    memcpy(dis,sum,sizeof(sum));
    while(s<=t) {
        x=zz[s%maxn];
        for(y=ff[x];y;y=nn[y]) {
            z=tt[y];
            if(dis[z]>=dis[x]+sum[z]) continue;
            dis[z]=dis[x]+sum[z];
            if(!vis[z]) {
                vis[z]=1;t++;
                zz[t%maxn]=z;
            }
        }
        s++;vis[x]=0;
    }
}
 
int main() {
    n=read();m=read(); int x,y;
    for(int i=1;i<=m;++i) {
        x=read();y=read();
        add(x,y);
    }
    for(int i=1;i<=n;++i) v[i]=read();
    S=read();x=read();
    for(int i=1;i<=x;++i) {
        y=read();G.insert(y);
    }
    tj(S);
    for(int i=1;i<=n;++i) for(int y=fir[i];y;y=nxt[y]) 
        if(xd[i]!=xd[to[y]]) bld(xd[i],xd[to[y]]);
    spfa(xd[S]);
    for(it=G.begin();it!=G.end();++it) {
        x=xd[*it];ans=max(ans,dis[x]);
    }
    printf("%d",ans);
    return 0;
}

  

posted @ 2017-09-12 17:23  shixinyi  阅读(131)  评论(0编辑  收藏  举报