【wikioi】1034 家园(最大流+特殊的技巧)
http://wikioi.com/problem/1034/
太神了這題。
其實一開始我以為是費用流,但是總感覺不對。
原因是我沒看到一句話,特定的時刻到達特定的點!!
也就是說,并不是每艘船每次都從起點到終點,所以裸的費用流肯定不行。
翻了題解。。
好恐怖,,按時間拆點。
每一時刻的太空站我們都拆一個點,然后將上一時刻的太空站向這一時刻的太空站連一條容量為oo的邊,表示在上一時刻太空站待著的人可以在這一時刻登船
然后每一時刻飛船都向對應時刻所到達的太空站連容量為飛船容量的邊。
然后每一次都跑最大流,將人數k減去最大流,當k小于0的時候,答案就是這一時刻。(經測試,時刻設為100耗時20ms,時刻設為30也能ac耗時10ms)
#include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> using namespace std; #define rep(i, n) for(int i=0; i<(n); ++i) #define for1(i,a,n) for(int i=(a);i<=(n);++i) #define for2(i,a,n) for(int i=(a);i<(n);++i) #define for3(i,a,n) for(int i=(a);i>=(n);--i) #define for4(i,a,n) for(int i=(a);i>(n);--i) #define CC(i,a) memset(i,a,sizeof(i)) #define read(a) a=getint() #define print(a) printf("%d", a) #define dbg(x) cout << #x << " = " << x << endl #define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; } inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; } inline const int max(const int &a, const int &b) { return a>b?a:b; } inline const int min(const int &a, const int &b) { return a<b?a:b; }const int N=5010, M=2000000, oo=~0u>>1, s=5000, t=s+1; int ihead[N], cnt=1, d[N], p[N], cur[N], gap[N], n, m, k, S[25], H[25], a[25][30]; struct ED { int from, to, cap, w, next; } e[M]; inline void add(const int &u, const int &v, const int &c) {e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v; e[cnt].from=u; e[cnt].cap=c;e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].to=u; e[cnt].from=v; e[cnt].cap=0; } inline void update(const int &T) {for1(i, 0, n+1) add(i+(T-1)*22, i+T*22, oo);int u, v;for1(i, 1, m) {u=(T-1)*22+a[i][(T-1)%S[i]];v=T*22+a[i][T%S[i]];add(u, v, H[i]);} } int isap(const int &s, const int &t, const int &n) {for1(i, 0, t) cur[i]=ihead[i];CC(d, 0); CC(gap, 0);int ret=0, i, f, u=s;gap[0]=n;while(d[s]<n) {for(i=cur[u]; i; i=e[i].next) if(e[i].cap && d[u]==d[e[i].to]+1) break;if(i) {p[e[i].to]=cur[u]=i; u=e[i].to;if(u==t) {for(f=oo; u!=s; u=e[p[u]].from) f=min(f, e[p[u]].cap);for(u=t; u!=s; u=e[p[u]].from) e[p[u]].cap-=f, e[p[u]^1].cap+=f;ret+=f;}}else {if(! (--gap[d[u]]) ) break;d[u]=n; cur[u]=ihead[u];for(i=ihead[u]; i; i=e[i].next) if(e[i].cap && d[u]>d[e[i].to]+1) d[u]=d[e[i].to]+1;++gap[d[u]];if(u!=s) u=e[p[u]].from;}}return ret; } int main() {read(n); read(m); read(k);for1(i, 1, m) {read(H[i]); read(S[i]);rep(j, S[i]) {read(a[i][j]);if(a[i][j]==-1) a[i][j]=n+1;}}for1(i, 0, 100) add(s, i*22, oo), add((n+1)+i*22, t, oo);for1(i, 1, 100) {update(i);k-=isap(s, t, t);if(k<=0) { print(i); return 0; }}print(0);return 0; }?
?
?
?
題目描述 Description
由于人類對自然的瘋狂破壞,人們意識到在大約2300年之后,地球不能再居住了,于是在月球上建立了新的綠地,以便在需要時移民。令人意想不到的是,2177年冬由于未知的原因,地球環境發生了連鎖崩潰,人類必須在最短的時間內遷往月球。
現 有n個太空站處于地球與月球之間(編號1..n),m艘公共交通太空船在其中來回穿梭,每個太空站Si可容納無限的人,每艘太空船pi只可容納Hpi人。 對于每一艘太空船pi,將周期性地停靠一系列的太空站(Si1,Si2…Sir),如:(1,3,4)表示停靠太空站1 3 4 1 3 4 1 3 4 …。 任一艘太空船從任一個太空站駛往另一個任意的太空站耗時為1。人只能在太空船停靠太空站(或地球、月球)時上船或下船。初始時的人全在地球上,太空船全在 初始站(太空船pi處于Si1),目標是讓所有的人盡快地全部轉移到月球上。
輸入描述 Input Description
文件第一行為三個正整數 n(太空站個數)、 m(太空船個數)、 k(需要運送的地球上的人的個數),其中 1<=m<=13, 1<=n<=20, 1<=k<=50。
接 下來的n行給出了太空船的信息,第i+1行說明太空船pi,此行第一個數表示pi可容納的人數Hpi,第二個數表示pi停靠一個周期的太空站個數 r,1<=r<=n+2, 隨后r個數便是停靠的太空站的編號(Si1,Si2,…,Sir), 地球用0表示,月球用-1表示。0時刻時,所有太空船都在初始站,隨后開始運行,在時刻1,2,3…等正點時刻各艘太空船停靠相應的太空站,即人只有在 0,1,2…等正點時刻才能上下太空船。
輸出描述 Output Description
文件只有一個數,若問題有解,輸出完成全部人員安全轉移的時刻,否則輸出0。
樣例輸入 Sample Input
2 2 1?
1 3 0 1 2
1 3 1 2 –1
樣例輸出 Sample Output
5
數據范圍及提示 Data Size & Hint
?1<=m<=13, 1<=n<=20, 1<=k<=50。
?
轉載于:https://www.cnblogs.com/iwtwiioi/p/3941051.html
總結
以上是生活随笔為你收集整理的【wikioi】1034 家园(最大流+特殊的技巧)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TQ210 —— LCD
- 下一篇: BUUCTF(web刷题记录一)