P1938 [USACO09NOV]找工就业Job Hunt spfa 点权转边
作者:互联网
奶牛们正在找工作。农场主约翰知道后,鼓励奶牛们四处碰碰运气。而且他还加了一条要求:一头牛在一个城市最多只能赚D(1≤D≤1000)美元,然后它必须到另一座城市工作。当然,它可以在别处工作一阵子后又回到原来的城市再最多赚D美元。而且这样的往返次数没有限制。
城市间有P(1≤P≤150)条单向路径连接,共有C(2≤C≤220)座城市,编号从1到C。奶牛贝茜当前处在城市S(1≤S≤C)。路径i从城市A_i到城市B_i(1≤A_i≤C,1≤B_i≤C),在路径上行走不用任何花费。
为了帮助贝茜,约翰让它使用他的私人飞机服务。这项服务有F条(1≤F≤350)单向航线,每条航线是从城市J_i飞到另一座城市K_i(1≤J_i≤C,1≤K_i≤C),费用是T_i(1≤T_i≤50000)美元。如果贝茜手中没有现钱,可以用以后赚的钱来付机票钱。
贝茜可以选择在任何时候,在任何城市退休。如果在工作时间上不做限制,贝茜总共可以赚多少钱呢?如果赚的钱也不会出现限制,就输出-1。
输入输出格式
输入格式:
第一行:5个用空格分开的整数D,P,C,F,S。
第2到第P+1行:第i+1行包含2个用空格分开的整数,表示一条从城市A_i到城市B_i的单向路径。
接下来F行,每行3个用空格分开的整数,表示一条从城市J_i到城市K_i的单向航线,费用是T_i。
输出格式:
一个整数,在上述规则下最多可以赚到的钱数。
输入输出样例
输入样例#1: 复制100 3 5 2 1 1 5 2 3 1 4 5 2 150 2 5 120输出样例#1: 复制
250
点转化为边存在一个问题 那就是遍历的路径上 点肯定是比边要多的 那么可以把其实点先看作0 最后再加上就可以了
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define LL long long #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define inf 2147483647 const int N=500000+50; int dis[N],vis[N],head[N],n,m,s,pos,k,L,R,ans,a[N],x,y,z; struct Edge { int next,v,to; }edge[N]; void add(int a,int b,int c) { edge[++pos]=Edge{head[a],c,b}; head[a]=pos; } void spfa(int s) { queue<int>q; rep(i,1,n) dis[i]=-inf,vis[i]=0; q.push(s); dis[s]=0; vis[s]=1; while(!q.empty()) { int u=q.front();q.pop(); vis[u]=0; for(int i=head[u];i;i=edge[i].next) { int v=edge[i].to; if(dis[v]<dis[u]+edge[i].v) { dis[v]=dis[u]+edge[i].v; if(vis[v]==0) { vis[v]=1; q.push(v); } } } } } int d,p,c,f; int main() { RIII(d,p,c);RII(f,s); rep(i,1,p) { int a,b;RII(a,b);add(a,b,d); } rep(i,1,f) { int a,b,c;RIII(a,b,c);add(a,b,d-c); } spfa(s); int ans=0; rep(i,1,c) ans=max(ans,dis[i]); cout<<ans+d; return 0; }View Code
标签:USACO09NOV,路径,int,贝茜,P1938,Hunt,单向,城市,dis 来源: https://www.cnblogs.com/bxd123/p/10960867.html