解析:
题目释义:一张图有c个节点,每个节点有一个相等的权值d,有p条无需花费的路径和f条需要花费的路径,求图中最长路。
算法设计:
由于可能出现正环,所以需要SPFA算法,在加边的时候把p条无需花费的路径边权设为d,而f条需要花费的路径设为d-z(其中z是这条路需要的花费)。由于终点不定,所以最后打擂台取最大值即可。
算法步骤:
1)读入,邻接表存边,存法上文已经提到
2)跑SPFA求最长路+判正环,如果有正环就可以无限走,输出-1直接退出
3)打擂台取最大值输出即可
参考程序如下:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #include<algorithm> using namespace std; int d,p,c,f,s,x,y,z,v[100001],w[100001],head[100001],nxt[100001],r[100001],cnt,maxx,dist[100001]; bool vis[100001]; void add(int a,int b,int c) { v[++cnt]=b; w[cnt]=c; nxt[cnt]=head[a]; head[a]=cnt; } void read() { cin>>d>>p>>c>>f>>s; for(int i=1;i<=p;i++) { cin>>x>>y; add(x,y,d); } for(int i=1;i<=f;i++) { cin>>x>>y>>z; add(x,y,d-z); } } void pr() { for(int i=1;i<=c;i++) { maxx=max(maxx,dist[i]); } cout<<maxx; } void spfa(int s) { memset(dist,-1,sizeof(dist)); queue<int>q; q.push(s); vis[s]=1; dist[s]=d; while(!q.empty()) { int t=q.front(); q.pop(); vis[t]=0; r[t]++; if(r[t]==c) { cout<<"-1"; exit(0); } for(int i=head[t];i;i=nxt[i]) { int y=v[i]; if(dist[y]<dist[t]+w[i]) { dist[y]=dist[t]+w[i]; if(!vis[y]) { q.push(y); vis[y]=1; } } } } } int main() { read(); spfa(s); pr(); return 0; }
P1938 [USACO09NOV]找工就业Job Hunt
原文:https://www.cnblogs.com/szmssf/p/10989152.html