BZOJ 2019 [Usaco2009 Nov]找工作:spfa最长路判正环

Posted Leohh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2019 [Usaco2009 Nov]找工作:spfa最长路判正环相关的知识,希望对你有一定的参考价值。

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2019

题意:

  奶牛们没钱了,正在找工作。农夫约翰知道后,希望奶牛们四处转转,碰碰运气。

  而且他还加了一条要求:一头牛在一个城市最多只能赚D(1 <= D <= 1,000)美元,然后它必须到另一座城市工作。当然,它可以在别处工作一阵后又回来原来的城市再最多赚D美元。而且这样往往返返的次数没有限制。

  城市间有P (1 <= P <= 150)条单向路径连接,共有N(2 <= N <= 220)座城市,编号1..N. 贝希当前处在城市S (1 <= S <= N)。路径 i 从城市A[i]到城市B[i](1 <= A[i] <= N, 1 <= B[i] <= N),在路径上行走不用花任何费用。

  为了帮助贝希,约翰让它使用他的私人飞机服务。这项服务有F条(1 <= F <= 350)航线,每条航线是从城市J[i]飞到另一座城市K[i](1 <=J[i] <= N, 1 <= K[i] <= N),费用是T[i] (1 <= T[i] <= 50,000)美元。

  如果贝希手中如果没有现钱,可以用以后赚的钱来付机票钱。

  贝希可以选择任何时候,在任何城市退休。

  如果在工作时间上不作限制,贝希总共可以赚多少钱呢?如果赚的钱也不会出现限制,就输出-1。

 

题解:

  spfa找最长路。

  如果有点入队超过n次,则存在正环,return -1。

  建边:

    (1)对于城市间的道路,边权设为D。

    (2)对于航线,边权设为D - T[i]。

 

AC Code:

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <vector>
  5 #include <queue>
  6 #define MAX_N 250
  7 
  8 using namespace std;
  9 
 10 struct Edge
 11 {
 12     int dest;
 13     int len;
 14     Edge(int _dest,int _len)
 15     {
 16         dest=_dest;
 17         len=_len;
 18     }
 19     Edge(){}
 20 };
 21 
 22 int n,p,f,d,s;
 23 int ans;
 24 int dis[MAX_N];
 25 int cnt[MAX_N];
 26 bool vis[MAX_N];
 27 vector<Edge> edge[MAX_N];
 28 queue<int> q;
 29 
 30 void read()
 31 {
 32     cin>>d>>p>>n>>f>>s;
 33     int a,b,c;
 34     for(int i=0;i<p;i++)
 35     {
 36         cin>>a>>b;
 37         edge[a].push_back(Edge(b,d));
 38     }
 39     for(int i=0;i<f;i++)
 40     {
 41         cin>>a>>b>>c;
 42         edge[a].push_back(Edge(b,d-c));
 43     }
 44 }
 45 
 46 int get_front()
 47 {
 48     int now=q.front();
 49     q.pop();
 50     vis[now]=false;
 51     return now;
 52 }
 53 
 54 void insert(int now)
 55 {
 56     if(vis[now]) return;
 57     q.push(now);
 58     vis[now]=false;
 59     cnt[now]++;
 60 }
 61 
 62 int spfa(int start)
 63 {
 64     memset(dis,0x80,sizeof(dis));
 65     memset(cnt,0,sizeof(cnt));
 66     memset(vis,false,sizeof(vis));
 67     insert(start);
 68     dis[start]=d;
 69     int res=d;
 70     while(!q.empty())
 71     {
 72         int now=get_front();
 73         for(int i=0;i<edge[now].size();i++)
 74         {
 75             Edge temp=edge[now][i];
 76             if(dis[temp.dest]<dis[now]+temp.len)
 77             {
 78                 dis[temp.dest]=dis[now]+temp.len;
 79                 insert(temp.dest);
 80                 if(cnt[temp.dest]>n) return -1;
 81                 res=max(res,dis[temp.dest]);
 82             }
 83         }
 84     }
 85     return res;
 86 }
 87 
 88 void solve()
 89 {
 90     ans=spfa(s);
 91 }
 92 
 93 void print()
 94 {
 95     cout<<ans<<endl;
 96 }
 97 
 98 int main()
 99 {
100     read();
101     solve();
102     print();
103 }

 

以上是关于BZOJ 2019 [Usaco2009 Nov]找工作:spfa最长路判正环的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1770: [Usaco2009 Nov]lights 燈

bzoj 1770: [Usaco2009 Nov]lights 燈

bzoj2017[Usaco2009 Nov]硬币游戏*

BZOJ 2017: [Usaco2009 Nov]硬币游戏(A Coin Game)

bzoj 1770 [Usaco2009 Nov]lights 燈 meet in the middle

BZOJ 1770: [Usaco2009 Nov]lights 燈 [高斯消元XOR 搜索]