抢掠计划

Siruseri 城中的道路都是单向的。不同的道路由路口连接。按照法律的规定,在每个路口都设立了一个 Siruseri 银行的 ATM 取款机。令人奇怪的是,Siruseri 的酒吧也都设在路口,虽然并不是每个路口都设有酒吧。
Banditji 计划实施 Siruseri 有史以来最惊天动地的 ATM 抢劫。他将从市中心出发,沿着单向道路行驶,抢劫所有他途径的 ATM 机,最终他将在一个酒吧庆祝他的胜利。
使用高超的黑客技术,他获知了每个 ATM 机中可以掠取的现金数额。他希望你帮助他计算从市中心出发最后到达某个酒吧时最多能抢劫的现金总数。他可以经过同一路口或道路任意多次。但只要他抢劫过某个 ATM 机后,该 ATM 机里面就不会再有钱了。
例如,假设该城中有 6 个路口,道路的连接情况如下图所示:
11.jpg

市中心在路口 1,由一个入口符号→来标识,那些有酒吧的路口用双圈来表示。每个 ATM 机中可取的钱数标在了路口的上方。在这个例子中,Banditji 能抢劫的现金总数为 47,实施的抢劫路线是:1−2−4−1−2−3−5。


一个强联通分量的所有的点都可以跑到,所以肯定是要缩点的,每个点的权值就是原来的和

然后再跑一遍最长路,从给出的酒吧中选一个即可

求最长路时不要写DFS的SPFA,会T

下面给出代码:

 

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
inline int rd(){
    int x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
inline void write(int x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
    return ;
}
int n,m;
int head[1000006],nxt[1000006],to[1000006];
int v[1000006];
int total=0;
void add(int x,int y){
    total++;
    to[total]=y;
    nxt[total]=head[x];
    head[x]=total;
    return ;
}
int dfn[1000006],low[1000006];
int tot=0;
int book[1000006];
int set=0;
int sta[1000006];
int color[1000006];
int cnt=0;
int v2[1000006];
void tarjan(int x){
    low[x]=dfn[x]=++tot;
    sta[++set]=x;
    book[x]=1;
    for(int e=head[x];e;e=nxt[e]){
        if(!dfn[to[e]]){
            tarjan(to[e]);
            low[x]=min(low[x],low[to[e]]);
        }
        else if(book[to[e]]) low[x]=min(low[x],dfn[to[e]]);
    }
    if(dfn[x]==low[x]){
        book[x]=0;
        cnt++;
        color[x]=cnt;
        v2[cnt]=v[x];
        while(set&&sta[set]!=x){
            int h=sta[set];
            book[h]=0;
            color[h]=cnt;
            v2[cnt]+=v[h];
            set--;
        }
        set--;
    }
    return ;
}
int head2[1000006],nxt2[1000006],to2[1000006];
int total2=0;
void add2(int x,int y){
    total2++;
    to2[total2]=y;
    nxt2[total2]=head2[x];
    head2[x]=total2;
    return ;
}
int dis[1000006];
int book2[1000006];
int vis[1000006];
int q[20000006];
int l=0,r=0;
void spfa(int x){
    vis[x]=1;
    q[++r]=x;
    dis[x]=v2[x];
    while(l<r){
        int y=q[++l];
        vis[y]=0;
        for(int e=head2[y];e;e=nxt2[e]){
            if(dis[to2[e]]<dis[y]+v2[to2[e]]){
                dis[to2[e]]=dis[y]+v2[to2[e]];
                if(!vis[to2[e]]){
                    q[++r]=to2[e];
                    vis[to2[e]]=1;
                }
            }
        }
    }
    return ;
}
int s,p;
int main(){
    n=rd(),m=rd();
    for(int i=1;i<=m;i++){
        int x=rd(),y=rd();
        add(x,y);
    }
    for(int i=1;i<=n;i++) v[i]=rd();
    for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
    for(int i=1;i<=n;i++) for(int e=head[i];e;e=nxt[e]) if(color[i]!=color[to[e]]) add2(color[i],color[to[e]]);
    s=rd(),p=rd();
    spfa(color[s]);
    int ans=0;
    for(int i=1;i<=p;i++){
        int x=rd();
        ans=max(ans,dis[color[x]]);
    }
    write(ans);
    return 0;
}

 

posted @ 2018-10-26 15:14  Bruce--Wang  阅读(204)  评论(0编辑  收藏  举报