BZOJ 2019 [Usaco2009 Nov]找工作:spfa【最長路】【判正環】

Leohh發表於2017-10-07

題目連結: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 }

 

相關文章