链接:https://ac.nowcoder.com/acm/contest/329/B
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
处女座想出去比赛,但是又不知道学校能不能给到足够的经费。然而处女座是大众粉丝,有着很好的人缘,于是他找了一个在学校管经费的地方勤工俭学偷来了一份报销标准。
由于处女座是万人迷,所以他在中间途径的每一条线路上都会发生一些故事,也许是粉丝给他发了一个200元的微信红包,也许是和他的迷妹一起吃饭花了500元。
而经费负责人也实地考察了每一条路线,在每一条路上,也许是天降红包雨,也许是地生劫匪。每一条路上都有属于自己的奇遇。
而经费负责人也只能根据他的故事决定这一路批下来多少经费。他会找出从宁波到比赛地的最小花费,并以此作为标准给处女座打比赛。而处女座也会选择对他来说最小花费的路线,来节省使用。
处女座想知道,最终的经费是否够用,如果够还会剩下来多少钱。如果不够,他自己要自费掏出多少钱。(当然处女座和经费管理人都具有旅途中无限信贷额度,所有收入支出会在旅行结束后一起结算。)
输入描述:
输入文件第一行包含一个整数T,表示处女座要参加的比赛场数。
对于每一场比赛,第一行包含两个整数N,M,分别表示旅行中的站点数(其中宁波的编号为1,比赛地的编号为N)和线路数。
接下来M行,每一行包含5个整数u,v,c,cnz,jffzr,分别表示从u到v有一条单向的线路,这条线路的票价为c。处女座搭乘这条线路的时候,会得到cnz元(如果为负即为失去-cnz元);经费负责人搭乘这条线路的时候,会得到jffzr元(如果为负即为失去-jffzr元)。
行程保证不会形成环,并保证一定能从宁波到达比赛地。
输出描述:
对于每一场比赛,如果经费负责人给出的经费绰绰有余,则先在一行输出"cnznb!!!",并在下一行输出他可以余下的经费;如果处女座的经费不够用,则先在一行输出"rip!!!",并在下一行输出他需要自费的金额;如果经费负责人给出的经费正好够处女座用,则输出一行"oof!!!"。(所有输出不含引号)
示例1
备注:
T≤10T≤10
2≤N≤1052≤N≤105
1≤M≤2⋅1051≤M≤2⋅105
1≤u,v≤N1≤u,v≤N
0≤c≤1090≤c≤109
−109≤cnz,jffzr≤109
想必读完后都知道是一个最短路的题目,
由于走一个边或许收到的红包比消费高,所以有负边的情况。忽略dijkstra算法。
然后出题人默认的出了数据卡掉了SPFA的算法,BELLMAN算法显然不符合时间复杂度。
然后我们分析一下。
2≤N≤1052≤N≤105
这显然是一个稀疏图,(定义自行排序)并且题目里的条件说明这个图是一个有向无环图,那么我们可以根据跑出来的拓扑排序然后求出最短路。
坑点:如果两个人的消费为负值,即到达了目的地还赚钱,那么不即消费为负值,而是0,即无消费。
细节见我的代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #define sz(a) int(a.size()) #define all(a) a.begin(), a.end() #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), '\0', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define gg(x) getInt(&x) #define db(x) cout<<"== [ "<<x<<" ] =="<<endl; using namespace std; typedef long long ll; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;} inline void getInt(int* p); const int maxn=1e5+8; const int mx = maxn; struct edge { ll cost; int to; void read() { scanf("%d%lf", &to, &cost); } edge(){} edge(int tt,ll c) { to=tt; cost=c; } } e; vector<edge> G[mx]; vector<edge> E2[mx]; ll disTo[mx]; bool vis[mx]; int topo[mx], cnt; void dfs(int i) { vis[i] = true; for (int j = 0; j < G[i].size(); ++j) if (!vis[G[i][j].to]) dfs(G[i][j].to); topo[cnt++] = i; } /// 有向无环图上的最短路 void dagSP(int s) { int i = cnt, j, v; while (topo[--i] != s); /// 先在topo中找到s memset(disTo, 0x3f, sizeof(disTo)); disTo[s] = 0; for (; i >= 0; --i) { v = topo[i]; for (j = 0; j < G[v].size(); ++j) { e = G[v][j]; /// v视作e.from disTo[e.to] = min(disTo[e.to], disTo[v] + e.cost); } } } void dagSP2(int s) { int i = cnt, j, v; while (topo[--i] != s); /// 先在topo中找到s memset(disTo, 0x3f, sizeof(disTo)); disTo[s] = 0; for (; i >= 0; --i) { v = topo[i]; for (j = 0; j <E2[v].size(); ++j) { e = E2[v][j]; /// v视作e.from disTo[e.to] = min(disTo[e.to], disTo[v] + e.cost); } } } int n; int main() { int t; gg(t); while(t--) { gg(n); for (int i = 0; i < n; ++i) G[i].clear(),E2[i].clear(); int m; int a,b,c,de,e; gg(m); repd(i,1,m) { scanf("%d %d %d %d %d",&a,&b,&c,&de,&e); G[a].pb(edge(b,c-de)); E2[a].pb(edge(b,c-e)); } MS0(vis); cnt = 0; for (int i = 0; i < n; ++i) if (!vis[i]) dfs(i); dagSP(1); ll cnz=disTo[n]; if(cnz<0) cnz=0ll; dagSP2(1); ll jw=disTo[n]; if(jw<0) jw=0ll; // db(cnz); // db(jw); if(cnz==jw) { printf("oof!!!\n"); }else if(cnz<jw) { printf("cnznb!!!\n"); printf("%lld\n",jw-cnz ); }else { printf("rip!!!\n"); printf("%lld\n",cnz-jw); } // E.clear(); // E2.clear(); // init(); } return 0; } inline void getInt(int* p) { char ch; do { ch = getchar(); } while (ch == ' ' || ch == '\n'); if (ch == '-') { *p = -(getchar() - '0'); while ((ch = getchar()) >= '0' && ch <= '9') { *p = *p * 10 - ch + '0'; } } else { *p = ch - '0'; while ((ch = getchar()) >= '0' && ch <= '9') { *p = *p * 10 + ch - '0'; } } }