Tyvj1139 向远方奔跑(APIO 2009 抢掠计划)

Posted ACforever

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tyvj1139 向远方奔跑(APIO 2009 抢掠计划)相关的知识,希望对你有一定的参考价值。

描述

    在唐山一中,吃饭是一件很令人头疼的事情,因为你不可能每次都站在队伍前面买饭,所以,你最需要做的一件事就是——跑饭。而跑饭的道路是无比艰难的,因为路是单向的(你要非说成是双向的我也没法,前提是你可以逆着2000+个狂热的跑饭群众而行),所以要合理选择路线。并且,在抵达你的目的地——板面馆之前,你需要先买一些干粮,比如烧饼之类的。现在给你每个干食商店的位置和干食喜爱度,请你设计一个跑饭方案使得在到达板面馆之前能得到尽可能多的干食喜爱度。

输入格式

    第一行包含两个整数N、M。N表示食品商店的个数,M表示道路条数。接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道 路的起点和终点的食品商店编号。接下来N行,每行一个整数,按顺序表示每个食品商店处的干食喜爱度。接下来一行包含两个整数S、P,S表示学校的编号,也就是出发地点。P表示板面馆数目。接下来的一行中有P个整数,表示P个卖板面的食品商店的编号。

输出格式

输出一个整数,表示到达板面馆之前能得到的最多的干食喜爱度。

测试样例1

输入

6 7 
1 2 
2 3 
3 5 
2 4 
4 1 
2 6 
6 5 
10 
12 

16 


1 4 
4 3 5 6

输出

47

备注

40%的数据n,m<=300   100%的数据n,m<=3000 

思路:

1、分析路可以重复走,想到强连通分量,如果强连通分量里面有一个点被访问,那么整个强连通分量都要被访问,否则答案偏小,于是先tarjan再缩点

2、缩点之后,整个图由一个有向有环图变为一个有向无环图,于是spfa处理,然后就AC了(bzoj上的好像能卡掉,WYW用tarjan写信息传递好像被卡了)

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
#include<queue>
#include<stack>
#define maxn 3005
#define maxint ~0U>>1
using namespace std;
stack<int> sta;
vector<int> comp[maxn];
int incomp[maxn],instack[maxn],dfn[maxn],low[maxn];
int index,cnum;
int n,m,q,d[maxn],rice[maxn],noodle[maxn],v[maxn],s,p,ans;
vector<int> g[maxn],nowg[maxn];
int nowrice[maxn],nownoodle[maxn],nows;
void input(){
    cin>>n>>m;
    int u,v;
    for(int i = 1;i <= m;i++){
        scanf("%d%d",&u,&v);
        g[u].push_back(v);
        
    }
    for(int i = 1;i <= n;i++){
        scanf("%d",&rice[i]);
    }
    cin>>s>>p;
    int nnow;
    for(int i = 1;i <= p;i++){
        scanf("%d",&nnow);
        noodle[nnow] = 1;
    }
}
void tarjan(int u){
    instack[u] = 2;
    dfn[u] = low[u] = ++index;
    sta.push(u);
    for(int i = 0;i < g[u].size();i++){
        int j = g[u][i];
        if(!dfn[j]){
            tarjan(j);
            low[u] = min(low[u],low[j]);
        }else if(instack[j] == 2){
            low[u] = min(low[u],dfn[j]);
        }
    }
    if(dfn[u] == low[u]){
        ++cnum;
        while(!sta.empty()){
            int t = sta.top();
            sta.pop();
            instack[t] = 1;
            incomp[t] = cnum;
            comp[cnum].push_back(t);
            if(t == u){
                break;
            }
        }
    }
}
void work(){
    for(int i = 1;i <= n;i++){
        if(!dfn[i]) tarjan(i);
    }
    int u,v,newu,newv;
    for(int i = 1;i <= n;i++){
        u = i;
        newu = incomp[u];
        nowrice[newu] += rice[u];
        if(noodle[u]) nownoodle[newu] = 1;
        if(u == s) nows = newu;
        for(int j = 0;j < g[u].size();j++){
            v = g[u][j];
            newv = incomp[v];
            if(newu == newv) continue;
            nowg[newu].push_back(newv);
        }
    }
}
void spfa(){
    queue<int> q;
    d[nows] = nowrice[nows];
    v[nows] = 1;
    q.push(nows);
    int xx,dd,to,wei;
    while(!q.empty()){
        xx = q.front();
        dd = d[xx];
        q.pop();
        v[xx] = 0;
        if(nownoodle[xx]) ans = max(ans,dd);
        for(int i = 0;i < nowg[xx].size();i++){
            to = nowg[xx][i];
            wei = nowrice[to];
            if(dd + wei > d[to]){
                d[to] = dd + wei;
                if(!v[to]){
                    v[to] = 1;
                    q.push(to);
                }
            }
        }
    }
    cout<<ans;
}
int main(){
    input();
    work();
    spfa();
    return 0;
}

 

以上是关于Tyvj1139 向远方奔跑(APIO 2009 抢掠计划)的主要内容,如果未能解决你的问题,请参考以下文章

1139: [POI2009]Wie

BZOJ 1179: [Apio2009]Atm

BZOJ 1179 Apio2009 Atm

[APIO2009]会议中心

APIO2009劫掠计划

P3627 [APIO2009]抢掠计划