[Apio2009][BZOJ1179] Atm

1179: [Apio2009]Atm

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 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

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;
}    

 

posted @ 2015-07-16 11:25  ws_fqk  阅读(258)  评论(0编辑  收藏  举报