P2648 赚钱
题目背景
改编自某题
题目描述
zzy现在决定环游中国,顺便赚点钱。zzy在一个城市最多只能赚D元,然后他可以选择退休也就是停止赚钱,或者去其它城市工作。当然,他可以在别处工作一阵子后又回到原来的城市再赚D元。这样的往返次数是没有任何限制的。
城市间有P条单向路径连接,共有C座城市,编号从1到C。路径i从城市Ai到城市Bi,在路径行走上不用任何花费。
zzy还可以乘飞机从某个城市飞到另一个城市。共有F条单向的航线,第i条航线是从城市Ji飞到另一座城市Ki,费用是Ti元。假如zzy身上没有现钱,他可以用以后赚的钱来付机票钱。
zzy可以从任何一个城市出发开始赚钱,并且选择在任何时候、任何城市退休。现在zzy想要知道,如果在工作时间上不做限制,那么zzy共可以赚多少钱呢?如果赚的钱也不会出现限制,那么就输出orz。
输入格式
第一行,4个用空格分开的正整数,D,P,C,F。
第二行到P+1行,第i+1行包含2个用空格分开的整数,表示一条从城市Ai到城市Bi的单向路径。
接下来的F行,每行3个用空格分开的正整数,表示一条从城市Ji到城市Ki的单向航线,费用为Ti。
输出格式
如果zzy赚的钱没有限制,输出orz。如果有限制,那么就输出在给定的规则下zzy最多可以赚到的钱数。
输入输出样例
输入 #1
100 3 5 2 1 5 2 3 1 4 5 2 150 2 5 120
输出 #1
250
说明/提示
对于100%的数据,1<=D<=1000,1<=P<=200,2<=C<=300,1<=F<=400。
分析
这没啥好分析的,这就和我之前的题解一毛一样,只不过要一个一个枚举,xiu
Code
#include<bits/stdc++.h> using namespace std; const int N = 1e3; int d,p,c,f; int x,y,w; int head[N],cnt; bool ed[N][N]; int tot[N]; int dis[N]; bool vis[N],ju; struct edge{ int to; int ne; int w; }e[N]; void add(int u,int v,int w){ e[++cnt].to = v; e[cnt].ne = head[u]; e[cnt].w = w; head[u] = cnt; } void spfa(int s){ ju = 0; for(int i = 1;i <= c;i++)dis[i] = -1e9; memset(vis,0,sizeof(vis)); memset(tot,0,sizeof(tot)); queue<int>q; q.push(s); dis[s] = d; vis[s] = 1; while(!q.empty()){ int f = q.front(); q.pop(); vis[f] = 0; for(int i = head[f];i;i = e[i].ne){ int v = e[i].to; if(dis[v] < dis[f] + e[i].w){ tot[v]++; if(tot[v]>c){ ju = 1; return ; } dis[v] = dis[f] + e[i].w; if(!vis[v]){ q.push(v); vis[v] = 0; } } } } } int main(){ scanf("%d%d%d%d",&d,&p,&c,&f); for(int i = 1;i <= p;i++){ scanf("%d%d",&x,&y); ed[x][y] = 1; add(x,y,d); } for(int i = 1;i <= f;i++){ scanf("%d%d%d",&x,&y,&w); if(!ed[x][y]){ add(x,y,d-w); } } int ans = -1e9; for(int i = 1;i <= c;i++){ spfa(i); if(ju == 1){ printf("orz\n"); return 0; } for(int j = 1;j <= c;j++){ ans = max(ans,dis[j]); } } printf("%d\n",ans); return 0; }