Lunch Time(費用流變型題,以時間為費用)
阿新 • • 發佈:2018-10-25
分享 miss lun represent 向上取整 empty true 新路 turn
Input
There are several test cases, please process till EOF.
The first line of each test case contains three integer N(2 <= N <= 2500), M(0 <= M <= 5000), K(0 <= K <= 109). Then follows M lines, each line has three numbers ai, bi, ci(0 <= ci <= 20), means there is an edge from vertex ai to bi with the capacity ci.
Lunch Time
http://acm.hdu.edu.cn/showproblem.php?pid=4807
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 782 Accepted Submission(s): 183
The first line of each test case contains three integer N(2 <= N <= 2500), M(0 <= M <= 5000), K(0 <= K <= 109). Then follows M lines, each line has three numbers ai, bi, ci(0 <= ci <= 20), means there is an edge from vertex ai
Output For each test case, print an integer represents the minimum time. If the requirements can not be met, print “No solution”(without quotes) instead.
Sample Input 5 6 4 0 1 2 0 3 1 1 2 1 2 3 1 1 4 1 3 4 2 3 3 10 0 1 1 1 2 1 0 2 1 2 0 1 Sample Output 3 6 No solution Source 2013ACM/ICPC亞洲區南京站現場賽——題目重現 參考博客:https://blog.csdn.net/u013761036/article/details/38268335
![技術分享圖片](/img/jia.gif)
1 #include<iostream> 2 #include<algorithm> 3 #include<queue> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 using namespace std; 8 9 const int INF=0x3f3f3f3f; 10 const int N=500005; 11 const int M=500005; 12 int top; 13 int dist[N],pre[N]; 14 bool vis[N]; 15 int c[N]; 16 int maxflow; 17 18 struct Vertex{ 19 int first; 20 }V[N]; 21 struct Edge{ 22 int v,next; 23 int cap,flow,cost; 24 }E[M]; 25 26 void init(int n){ 27 for(int i=0;i<=n;i++){ 28 V[i].first=-1; 29 } 30 top=0; 31 maxflow=0; 32 } 33 34 void add_edge(int u,int v,int c,int cost){ 35 E[top].v=v; 36 E[top].cap=c; 37 E[top].flow=0; 38 E[top].cost=cost; 39 E[top].next=V[u].first; 40 V[u].first=top++; 41 } 42 43 void add(int u,int v,int c,int cost){ 44 add_edge(u,v,c,cost); 45 add_edge(v,u,0,-cost); 46 } 47 48 bool SPFA(int s,int t,int n){ 49 int i,u,v; 50 queue<int>qu; 51 for(i=0;i<=n;i++){ 52 dist[i]=INF; 53 vis[i]=false; 54 c[i]=0; 55 pre[i]=-1; 56 } 57 vis[s]=true; 58 c[s]++; 59 dist[s]=0; 60 qu.push(s); 61 while(!qu.empty()){ 62 u=qu.front(); 63 qu.pop(); 64 vis[u]=false; 65 for(i=V[u].first;~i;i=E[i].next){ 66 v=E[i].v; 67 if(E[i].cap>E[i].flow&&dist[v]>dist[u]+E[i].cost){ 68 dist[v]=dist[u]+E[i].cost; 69 pre[v]=i; 70 if(!vis[v]){ 71 c[v]++; 72 qu.push(v); 73 vis[v]=true; 74 if(c[v]>n){ 75 return false; 76 } 77 } 78 } 79 } 80 } 81 if(dist[t]==INF){ 82 return false; 83 } 84 return true; 85 } 86 87 int MCMF(int s,int t,int n,int k){ 88 if(k==0) return 0;////////////*******************//// 89 int d; 90 int i,mincost; 91 mincost=0; 92 int ans=INF; 93 int sum_peo=k,now_peo=0,list_time=0; 94 while(SPFA(s,t,n)){ 95 d=INF; 96 for(i=pre[t];~i;i=pre[E[i^1].v]){ 97 d=min(d,E[i].cap-E[i].flow); 98 } 99 maxflow+=d; 100 for(i=pre[t];~i;i=pre[E[i^1].v]){ 101 E[i].flow+=d; 102 E[i^1].flow-=d; 103 } 104 mincost+=dist[t]*d; 105 sum_peo-=(dist[t]-list_time)*now_peo+d; 106 list_time=dist[t],now_peo+=d; 107 int now=dist[t]+(int)ceil((1.0*(sum_peo<0?0:sum_peo))/now_peo); 108 if(ans>now) ans=now; 109 if(sum_peo<1) break; 110 } 111 return ans; 112 } 113 114 int main(){ 115 int n,m,k; 116 int v,u,w,c; 117 int s,t; 118 while(~scanf("%d %d %d",&n,&m,&k)){ 119 s=0,t=n-1; 120 init(n); 121 for(int i=1;i<=m;i++){ 122 scanf("%d %d %d",&v,&u,&c); 123 add(v,u,c,1); 124 } 125 int ans=MCMF(s,t,n,k); 126 if(ans==INF) printf("No solution\n"); 127 else printf("%d\n",ans); 128 } 129 } 130 /* 131 題意: 132 給你一個有向圖,每條邊上都有每一時刻的最大流量,有k個人在點0, 133 他們要去點n-1,問你最晚到達的那個人最快要多久。 134 思路: 135 這道題目用該是借助費用流的找新路徑去枚舉,可以說是費用流變形吧, 136 首先我們一定要明白一點,就是時間的影響,單純的最大流如果在時間的基礎上考慮沒什麽意義, 137 而費用流呢,我們想象一下,如果把時間設成費用那麽我們就可以吧流量和時間結合起來了, 138 在費用流的過程中我們要知道,他每一次都是根據最短路去找新的路徑的, 139 也就是說路徑在費用上來說是遞增的(流量不一定), 140 那麽我們就可以根據這個特點來枚舉一那些路徑來過人, 141 要明白,如果起點到終點有兩條邊,一條很近,一條很遠, 142 有可能大家都走近的路徑(寧可排隊走),也不走遠的(所以直接最大流是錯了), 143 那麽我們就可以枚舉路徑了,路徑可以直接用費用流每次的路徑,因為時間遞增的, 144 對於每一次我們能過的人是多少呢?這個地方很關鍵,對於每一條路徑來說, 145 如果當前的路徑a距離是10,流量是15,那麽當時間大於10的時候,每過一個時間單位,路徑a都可以再過15個人, 146 所以當前的時間段的總人數是之前的總人數+(當前長度-上一個長度)* 上一個的總流量 + 當前流量 147 那麽如果現在當前這一部之前的所有路徑當路徑要花費的時間是多少呢 148 now = 當前長度+剩余的路徑長度/當前總流量 向上取整 149 這樣比較now和ans更新答案就行了, 150 還有一個地方要明確,就是當總人數超過全圖的最大流的時候答案就是 151 費用流中最長的路徑 + 總人數/全圖最大流 向上取整, 152 這個地方不用特判,上面的想法裏面包括在這裏,說了只是為了便於理解。 153 154 */View Code
Lunch Time(費用流變型題,以時間為費用)