BZOJ1179 : [Apio2009]Atm 缩点+spfa

1179: [Apio2009]Atm

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 2069  Solved: 826
[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就可以AC

///1085422276
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#include<bitset>
#include<set>
#include<vector>
using namespace std ;
typedef long long ll;
#define mem(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,127,sizeof(a));
#define memfy(a)  memset(a,-1,sizeof(a));
#define TS printf("111111\n");
#define FOR(i,a,b) for( int i=a;i<=b;i++)
#define FORJ(i,a,b) for(int i=a;i>=b;i--)
#define READ(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define mod 1000000007
#define inf 100000000
inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
//****************************************
#define maxn  500000+5
int pub,hav[maxn],s,top,vis[maxn],head[maxn],dist[maxn],belong[maxn],value[maxn],va[maxn],t,inq[maxn],q[maxn],scc,cnt;
int dfn[maxn],n,m,p,low[maxn],hea[maxn];
struct ss
{
    int to,next,u;
}e[maxn*2],newe[maxn*5];
void init()
{
    mem(head);mem(vis);scc=0;mem(hav);mem(hea);
    t=1;cnt=0;top=0;mem(va);mem(dist);
}
void add(int u,int v)
{
    e[t].next=head[u];
    e[t].to=v;
    e[t].u=u;
    head[u]=t++;
}
void addd(int u,int v)
{
    newe[t].to=v;
    newe[t].next=hea[u];
    hea[u]=t++;
}
void dfs(int x)
{
    vis[x]=inq[x]=1;
    low[x]=dfn[x]=++cnt;
    q[++top]=x;
    for(int i=head[x];i;i=e[i].next)
    {
        if(!vis[e[i].to])
        {
            dfs(e[i].to);
            low[x]=min(low[x],low[e[i].to]);
        }
        else if(inq[e[i].to]) low[x]=min(low[x],dfn[e[i].to]);
    }
    int v=-1;
    if(low[x]==dfn[x])
    {
       scc++;
        while(v!=x)
        {
            v=q[top--];
            inq[v]=0;
            belong[v]=scc;
            hav[scc]+=value[v];
        }
    }
}
void tarjan()
{
    FOR(i,1,n)if(!vis[i])dfs(i);
    t=1;mem(hea);
    FOR(i,1,n)
    {
        for(int j=head[i];j;j=e[j].next){
            if(belong[e[j].to]!=belong[i])
                addd(belong[i],belong[e[j].to]);
        }
    }
}
void spfa()
{
    queue<int >Q;
    Q.push(belong[s]);
    inq[belong[s]]=1;
    dist[belong[s]]=hav[belong[s]];
    while(!Q.empty())
    {
      int k=Q.front();
        Q.pop();
       inq[k]=0;
        for(int i=hea[k];i;i=newe[i].next)
        {
            if(dist[k]+hav[newe[i].to]>dist[newe[i].to])
            {
                dist[newe[i].to]=dist[k]+hav[newe[i].to];
                if(!inq[newe[i].to])
                {
                    inq[newe[i].to]=1;
                     Q.push(newe[i].to);
                }
            }
        }
    }

}
int main()
{

    n=read();
    m=read();
    int a,b;
    init();
    FOR(i,1,m)
    {
        scanf("%d%d",&a,&b);
        add(a,b);
    }
    FOR(i,1,n)scanf("%d",&value[i]);
    tarjan();
    s=read();
    p=read();
    spfa();
    int ans=-1;
    FOR(i,1,p)
    {
        scanf("%d",&pub);
        ans=max(ans,dist[belong[pub]]);
    }
    cout<<ans<<endl;
    return 0;
}
代码

 

posted @ 2015-09-26 00:13  meekyan  阅读(163)  评论(0编辑  收藏  举报