P1938 [USACO09NOV]找工就业Job Hunt

-------------------------

链接:Miku

---------------------------

这道题本质上还是一个spfa板子,考虑一下题目的条件,到达一个城市后,肯定会赚到d的钱,那么我们把这个钱视为在路上赚的,然后到达一个城市

立即去下一个城市,其实是等价的,我们就把边权转换成了点权。

----------------------------

再考虑一下飞机,能赚的钱减去机票钱既可以了,是个负数?题目说了可以赊账。

----------------------------

一直赚钱?这是什么东西,不过考虑一下把边权取负,这样能一直赚钱,不就是有负环了吗?而且还会有负边权,正好用spfa解决。

输出怎么办?建一个超级重点,就像是奶牛在退休后,免费去一个地方安享晚年,那么那个地方在哪并不重要,对吧?

---------------------------

记得取反,读入和输出的时候都是。

而且初始化的时候,他是可以在第一个城市赚到d元的,所以要注意初始化为-d

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int head[100001];
int cnt[1000001];
int pp;
struct b{
    int to;
    int v;
    int ne;
}e[100001];
int d,p,c,f,s;
int x,y,z;
int su;
int dis[100001];
int vis[100001];
queue <int> qu;
void add(int f,int to,int v){
    pp++;
    e[pp].v=v;
    e[pp].ne=head[f];
    e[pp].to=to;
    head[f]=pp;    
}
int main(){
    scanf("%d%d%d%d%d",&d,&p,&c,&f,&s);
    memset(dis,0x7f7f7f7f,sizeof(dis));
    for(int i=1;i<=p;++i){
        scanf("%d%d",&x,&y);
        add(x,y,-d);
    }
    su=c+1;
    for(int i=1;i<=f;++i){
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,-(d-z));
    }
    for(int i=1;i<=c;++i){
        add(i,su,0);
    }
    qu.push(s);
    vis[s]=1;
    dis[s]=-d;
    int cntt=0;
    do{
        int u=qu.front();
        qu.pop();
        vis[u]=0;
        for(int i=head[u];i;i=e[i].ne){
            int v=e[i].to;
            if(dis[v]>dis[u]+e[i].v){
                dis[v]=dis[u]+e[i].v;
                if(!vis[v]){
                    vis[v]=1;
                    cnt[v]++;
                    if(cnt[v]>c){
                        cout<<-1;
                        return 0;
                    }
                    qu.push(v);
                }
            }
        }
    }while(!qu.empty());
    cout<<-dis[su];
    return 0;
}
Ac
posted @ 2020-01-19 21:50  Simex  阅读(158)  评论(0编辑  收藏  举报