牛客寒假算法基礎集訓營3---B----處女座的比賽資格(拓撲排序處理有負邊的最短路)
阿新 • • 發佈:2019-01-27
man 接下來 pan style src sub 報銷 != type
空間限制:C/C++ 262144K,其他語言524288K
64bit IO Format: %lld
由於處女座是萬人迷,所以他在中間途徑的每一條線路上都會發生一些故事,也許是粉絲給他發了一個200元的微信紅包,也許是和他的迷妹一起吃飯花了500元。
而經費負責人也實地考察了每一條路線,在每一條路上,也許是天降紅包雨,也許是地生劫匪。每一條路上都有屬於自己的奇遇。
而經費負責人也只能根據他的故事決定這一路批下來多少經費。他會找出從寧波到比賽地的最小花費,並以此作為標準給處女座打比賽。而處女座也會選擇對他來說最小花費的路線,來節省使用。
處女座想知道,最終的經費是否夠用,如果夠還會剩下來多少錢。如果不夠,他自己要自費掏出多少錢。(當然處女座和經費管理人都具有旅途中無限信貸額度,所有收入支出會在旅行結束後一起結算。)
示例1
2≤N≤1052≤N≤105
鏈接:https://ac.nowcoder.com/acm/contest/329/B
來源:牛客網
空間限制: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 3 3 1 2 300 600 -600 2 3 100 -300 1 1 3 200 0 0
輸出
復制cnznb!!! 100
說明
處女座先走第一條路再走第二條路到達,總花費100元,經費負責人走第三條路,花費200元,處女座經費剩余100元
備註:
T≤10T≤102≤N≤1052≤N≤105
1≤M≤2⋅1051≤M≤2⋅1052≤N≤1052≤N≤105
1≤u,v≤N1≤u,v≤N
0≤c≤1090≤c≤109
−109≤cnz,jffzr≤109
想必讀完後都知道是一個最短路的題目,
由於走一個邊或許收到的紅包比消費高,所以有負邊的情況。忽略dijkstra算法。
然後出題人默認的出了數據卡掉了SPFA的算法,BELLMAN算法顯然不符合時間復雜度。
然後我們分析一下。
這顯然是一個稀疏圖,(定義自行排序)並且題目裏的條件說明這個圖是一個有向無環圖,那麽我們可以根據跑出來的拓撲排序然後求出最短路。
坑點:如果兩個人的消費為負值,即到達了目的地還賺錢,那麽不即消費為負值,而是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‘; } } }
牛客寒假算法基礎集訓營3---B----處女座的比賽資格(拓撲排序處理有負邊的最短路)