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 燈
BZOJ 2017: [Usaco2009 Nov]硬币游戏(A Coin Game)