【BZOJ1570】[JSOI2008]Blue Mary的旅行 動態加邊網絡流
阿新 • • 發佈:2017-05-15
efi 一次 第一次 dfs name jsoi2008 網絡公司 data cstring
第一行包含3個正整數N,M和T。題目中會出現的所有城市分別編號為1,2,…,N,其中城市A編號一定為1,城市B編號一定為N. U公司一共有M條(單向)航班。而連Blue Mary在內,公司一共有T個人要從A市前往B市。 以下M行,每行包含3個正整數X,Y,Z, 表示U公司的每一條航班的出發地,目的地以及Blue Mary最多能夠買到的這一航班某一天出發的票數。(即:無論是哪一天,Blue Mary最多只能買到Z張U航空公司的從城市X出發到城市Y的機票。) 輸入保證從一個城市到另一個城市的單向航班最多只有一個。
3 3 5
1 2 1
2 3 5
3 1 4
【BZOJ1570】[JSOI2008]Blue Mary的旅行
Description
在一段時間之後,網絡公司終於有了一定的知名度,也開始收到一些訂單,其中最大的一宗來自B市。Blue Mary決定親自去簽下這份訂單。為了節省旅行經費,他的某個金融顧問建議只購買U航空公司的機票。U航空公司的所有航班每天都只有一班,並且都是上午出發當天下午到達的,所以他們每人每天只能坐一班飛機。經過調查,他們得到了U航空公司經營的所有航班的詳細信息,這包括每一航班的出發地,目的地以及最多能買到的某一天出發的票數。(註意: 對於一個確定的航班,無論是哪一天,他們最多能買到的那一天出發的票數都是相同的。) Blue Mary註意到他們一定可以只乘坐U航空公司的航班就從A市到達B市,但是,由於每一航班能買到的票的數量的限制,他們所有人可能不能在同一天到達B市。所以現在Blue Mary需要你的幫助,設計一個旅行方案使得最後到達B市的人的到達時間最早。Input
Output
僅有一行,包含一個正整數,表示最後到達B市的人的最早到達時間。假設他們第一次乘飛機的那一天是第一天。Sample Input
1 2 1
2 3 5
3 1 4
Sample Output
6HINT
約定:
2 <= N <= 50
1 <= M <= 2450
1 <= T <= 50
1 <= X,Y <= N
X != Y
1 <= Z <= 50
題解:我們假設在tim時所有人都能到達終點,於是我們枚舉tim,將每個點拆成tim個,然後連邊跑最大流,若流量=T,說明tim就是答案
具體方法:用(i,j)表示將原來的i號節點拆成第j個點
1.S -> (0,0) 流量T
2.(i,j-1) -> (i,j) 流量∞ 3.對於邊(a,b,c) (a,j-1) -> (b,j) 流量c
4.(n,j) -> T 流量T
由於本人覺得點數比較多,感到很虛,所以用了動態加邊的最大流,56ms飛起~
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #define P(A,B) ((B)*n+A) using namespace std; int to[1000000],next[1000000],val[1000000],d[50010],head[50010],pa[2500],pb[2500],pc[2500]; int n,m,t,cnt,ans,sum,S,T,tim; queue<int> q; int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘)f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+gc-‘0‘,gc=getchar(); return ret*f; } void add(int a,int b,int c) { to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++; to[cnt]=a,val[cnt]=0,next[cnt]=head[b],head[b]=cnt++; } int bfs() { int i,u; memset(d,0,sizeof(d)); while(!q.empty()) q.pop(); d[S]=1,q.push(S); while(!q.empty()) { u=q.front(),q.pop(); for(i=head[u];i!=-1;i=next[i]) { if(!d[to[i]]&&val[i]) { d[to[i]]=d[u]+1; if(to[i]==T) return 1; q.push(to[i]); } } } return 0; } int dfs(int x,int mf) { if(x==T) return mf; int i,temp=mf,k; for(i=head[x];i!=-1;i=next[i]) { if(d[to[i]]==d[x]+1&&val[i]) { k=dfs(to[i],min(temp,val[i])); if(!k) d[to[i]]=0; val[i]-=k,val[i^1]+=k,temp-=k; if(!temp) break; } } return mf-temp; } int main() { n=rd(),m=rd(),t=rd(),tim=n+t; S=0,T=n*(tim+1)+1; memset(head,-1,sizeof(head)); add(S,1,t); int i,j,k,a,b,c; for(i=1;i<=m;i++) pa[i]=rd(),pb[i]=rd(),pc[i]=rd(); for(i=1;i<=tim;i++) { for(j=1;j<=m;j++) add(P(pa[j],i-1),P(pb[j],i),pc[j]); for(j=1;j<=n;j++) add(P(j,i-1),P(j,i),1<<30); add(P(n,i),T,t); while(bfs()) sum+=dfs(S,1<<30); if(sum==t) { printf("%d",i); return 0; } } }
【BZOJ1570】[JSOI2008]Blue Mary的旅行 動態加邊網絡流