【洛谷P1343】地震逃生 解題報告
阿新 • • 發佈:2018-12-14
P1343 地震逃生
題目描述
汶川地震發生時,四川XX中學正在上課,一看地震發生,老師們立刻帶領x名學生逃跑,整個學校可以抽象地看成一個有向圖,圖中有n個點,m條邊。1號點為教室,n號點為安全地帶,每條邊都只能容納一定量的學生,超過樓就要倒塌,由於人數太多,校長決定讓同學們分成幾批逃生,只有第一批學生全部逃生完畢後,第二批學生才能從1號點出發逃生,現在請你幫校長算算,每批最多能運出多少個學生,x名學生分幾批才能運完。
輸入輸出格式
輸入格式:
第一行3個整數n,m,x(\(x<2^{31},n \le 200,m \le 2000\));以下m行,每行三個整數a,b,c(a1,a<>b,0描述一條邊,分別代表從a點到b點有一條邊,且可容納c名學生。
輸出格式:
兩個整數,分別表示每批最多能運出多少個學生,x名學生分幾批才能運完。如果無法到達目的地(n號點)則輸出“Orz Ni Jinan Saint Cow!”
輸入輸出樣例
輸入樣例#1:
6 7 7
1 2 1
1 4 2
2 3 1
4 5 1
4 3 1
3 6 2
5 6 1
輸出樣例#1:
3 3
說明
【註釋】
比如有圖
1 2 100
2 3 1
100個學生先衝到2號點,然後1個1個慢慢沿2-3邊走過去
18神牛規定這樣是不可以的……
也就是說,每批學生必須同時從起點出發,並且同時到達終點
演算法
網路最大流。 請大家先掌握,這裡不詳細講。
思路
很明顯,1是源點,n是匯點,直接網路最大流模板即可。
這裡資料十分小,用Edmonds-Karp或Dinic都可以。
我才不告訴你EK怎麼打忘光了
用網路流求出了每次能通過的學生數ans後,就可以直接求出分成\(floor(frac{ans - 1}x) + 1\)次通過。總體來說不是很難,具體看程式碼QAQ
程式碼
#include<bits/stdc++.h> using namespace std; #define open(s) freopen( s".in", "r", stdin ), freopen( s".out", "w", stdout ) #define MAXN 205 #define MAXM 4005 //建雙向邊要開兩倍別忘了 int n, m, X, ans;//小寫的x會衝突(下5行) QAQ 只好改大寫 int hd[MAXN], nxt[MAXM], to[MAXM], val[MAXM], tot(1);//MAXN、MAXM別看錯了 ~~我才不告訴你為了這個我錯了好幾遍~~ //還有tot要賦值為1**千萬**別忘了 ~~我又為這個除錯了好久~~(不用成對儲存的請忽略這句話) int dis[MAXN]; queue<int> Q; int S, T; int x, y; void Add( int x, int y, int z ){nxt[++tot] = hd[x]; hd[x] = tot; to[tot] = y; val[tot] = z;}//鏈式前向星萬歲!~~雖然鄰接矩陣也可以~~ bool BFS(){//分層 while( !Q.empty() ) Q.pop();//清空queue 懶得手打佇列QAQ memset( dis, 0, sizeof dis );//初始化別忘了 Q.push(S); dis[S] = 1; while( !Q.empty() ){ x = Q.front(); Q.pop(); for ( int i = hd[x]; i; i = nxt[i] ){ if ( val[i] && !dis[to[i]] ){ dis[to[i]] = dis[x] + 1; Q.push( to[i] ); if ( to[i] == T ) return 1; } } } return 0; } int DFS( int x, int fl ){ if ( x == T ) return fl; int res(fl), k; for ( int i = hd[x]; i && res; i = nxt[i] ){ if ( ( dis[to[i]] == dis[x] + 1 ) && val[i] ){ k = DFS( to[i], min( res, val[i] ) ); if ( !k ) dis[to[i]] = 0; //剪枝! 不能再增廣的點去掉! val[i] -= k; val[i^1] += k; res -= k; //成對儲存 } } return fl - res; } int main(){ scanf( "%d%d%d", &n, &m, &X ); S = 1; T = n; for ( int i = 1; i <= m; ++i ){ int x, y, z; scanf( "%d%d%d", &x, &y, &z ); Add( x, y, z ); Add( y, x, 0 ); } int t; while( BFS() ) while( ( t = DFS( S, INT_MAX ) ) > 0 ) ans += t; if ( ans ) printf( "%d %d\n", ans, ( X - 1 ) / ans + 1 );//同上 else printf( "Orz Ni Jinan Saint Cow!\n" ); //這是誰? return 0; }