BZOJ 1179: [Apio2009]Atm【Trajan+最短路】

1179: [Apio2009]Atm


Time Limit: 15 Sec Memory Limit: 162 MB

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

题解

一眼的题目,tarjan+spfa(最短路)。o ( ^ v ^ ) o

代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 500005
using namespace std;
int n,m,top,tim,S,P,ans,moy[MAXN],low[MAXN],dfn[MAXN],stk[MAXN],fa[MAXN];
int que[MAXN],dst[MAXN],hd,tl;
bool istk[MAXN],vis[MAXN];
struct xcw{
    int tot,lnk[MAXN],nxt[MAXN],son[MAXN];
    void clear(){tot=0;memset(lnk,0,sizeof(lnk));memset(nxt,0,sizeof(nxt));memset(son,0,sizeof(son));}
    void add(int x,int y){son[++tot]=y,nxt[tot]=lnk[x],lnk[x]=tot;}
}a,b;
int read(){
    int ret=0;char ch=getchar();
    while(ch<'0'||'9'<ch) ch=getchar();
    while('0'<=ch&&ch<='9') ret=ret*10+ch-48,ch=getchar();
    return ret;
}
int tarjan(int x){
    low[x]=dfn[x]=++tim;
    istk[x]=1;stk[++top]=x;
    for(int j=a.lnk[x];j;j=a.nxt[j])
    if(dfn[a.son[j]]==0) tarjan(a.son[j]),low[x]=min(low[x],low[a.son[j]]);
    else if(istk[a.son[j]]) low[x]=min(low[x],dfn[a.son[j]]);
    if(dfn[x]==low[x]) do{istk[stk[top]]=0,fa[stk[top]]=x;}while(stk[top--]!=x);
}
void SPFA(int x){
    hd=0,que[tl=1]=x;vis[x]=1;dst[x]=moy[fa[S]];
    while(hd^tl){
        x=que[(++hd)%=MAXN],vis[x]=0;
        for(int j=b.lnk[x];j;j=b.nxt[j])
        if(dst[b.son[j]]<dst[x]+moy[b.son[j]]){
            dst[b.son[j]]=dst[x]+moy[b.son[j]];
            if(!vis[b.son[j]]) vis[b.son[j]]=1,que[(++tl)%=MAXN]=b.son[j];
        }
    }
}
int main(){
    n=read();m=read();
    for(int i=1;i<=m;i++){int x=read(),y=read();a.add(x,y);}
    for(int i=1;i<=n;i++) moy[i]=read(),fa[i]=i;
    for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
    b.clear();
    for(int i=1;i<=n;i++){
        if(fa[i]^i) moy[fa[i]]+=moy[i];
        for(int j=a.lnk[i];j;j=a.nxt[j]) if(fa[a.son[j]]^fa[i]) b.add(fa[i],fa[a.son[j]]);
    }
    S=fa[read()],P=read();
    SPFA(S);
    for(int i=1;i<=P;i++) ans=max(ans,dst[fa[read()]]);
    printf("%d\n",ans);
    return 0;
}

SOLVE

posted @ 2018-01-10 16:28  XSamsara  阅读(106)  评论(0编辑  收藏  举报