1. 程式人生 > >Lunch Time(費用流變型題,以時間為費用)

Lunch Time(費用流變型題,以時間為費用)

分享 miss lun represent 向上取整 empty true 新路 turn

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


Problem Description The campus of Nanjing University of Science and Technology can be viewed as a graph with N vertexes and M directed edges (vertexes are numbered from 0 to N - 1). Each edge has the same length 1. Every day, there are K students walking to the dinning-hall (vertex N - 1) from the teaching building (vertex 0) at lunch time. They all want reach the dinning-hall as soon as possible. However, each edge can only serve at most ci students at any time. Can you make arrangements for students, so that the last student can reach the dinning-hall as soon as possible? (It is assumed that the speed of the students is 1 edge per unit time)

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.

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 技術分享圖片
  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(費用流變型題,以時間為費用)