题意:给定n点m边有向图,每条边同时可以承载若干人同时经过,每个人的速度均为单位时间通过一条边。K个人从0点开始走向n-1点,问最后一个人走到n-1点的最早时间
解法:这道题目需要完全理解最大流最小费用流的原理:每次得到一条费用最小的增广路
容易得到对于每条增广路来说,我们单位时间向其路中传输a人(a为该增广路流量)最为合理。由增广路时间递增可知,消耗时间是当前增广路所用时间,当前已经运送的人总数可以通过逐次叠加得到。当总人数刚刚超过k时,返回即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define PII pair<int,int>
#include<map>
#include<vector>
#define MP make_pair
#include<map>
#include<bitset>
#include<math.h>
#define ll unsigned long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define X first
#define Y second
#define MP make_pair
using namespace std;
typedef pair<ll,int> PLI;
const int INF = 0X3f3f3f3f;
const int maxn = 5000+10;
int n,m,k;
struct{
int u,v,nxt,cost,flow,cap;
}e[maxn<<2];
int head[maxn],tot;
int ans;//已用时间
int now;//当前人数
int maxx;//之前增广路径的最长值
int sum;//当前单位时间总流量
int p[maxn<<2];
void add(int u,int v,int cost,int cap){
e[tot].u=u,e[tot].v=v,e[tot].nxt=head[u],e[tot].cost=cost,e[tot].cap=cap,e[tot].flow=0,head[u]=tot++;
}
void spfa(int S,int T,int d[]){
bool vis[maxn];
queue<int> q;
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++) d[i]=INF;
d[S]=0;
q.push(S);
while(!q.empty()){
int u=q.front(); q.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=e[i].nxt){
int v=e[i].v;
if(e[i].cap>e[i].flow&&d[v]>d[u]+e[i].cost){
d[v]=d[u]+e[i].cost;
p[v]=i;
if(!vis[v]){ vis[v]=1; q.push(v); }
}
}
}
}
void mcmf(int S,int T){
int c=0,f=0;
while(1){
int d[maxn];
spfa(S,T,d);
if(d[T]==INF) break;
int a=INF;//最小流量
for(int u=p[T];u!=-1;u=p[e[u].u]){
a=min(a,e[u].cap-e[u].flow);
}
for(int u=p[T];u!=-1;u=p[e[u].u]){
e[u].flow+=a;
e[u^1].flow-=a;
}
if((d[T]-maxx)*sum+now>=k){
ans=ceil((1.0*(k-now))/(sum*1.0))+maxx;
now=k;
return;
}
else if(now+(d[T]-maxx)*sum+a>=k){
ans=d[T];
now=k;
return;
}
else now+=((d[T]-maxx)*sum+a);
sum+=a,maxx=max(maxx,d[T]);
}
}
int main(){
//freopen("a.txt","r",stdin);
while(scanf("%d%d%d",&n,&m,&k)!=EOF){
memset(head,-1,sizeof(head)); tot=0;
memset(p,-1,sizeof(p));
for(int i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,1,z),add(y,x,-1,0);
}
if(!k){
printf("0\n");
continue;
}
ans=now=maxx=sum=0;
mcmf(0,n-1);
if(!now) printf("No solution\n");
else{
if(now>=k) printf("%d\n",ans);
else{
ans=ceil((1.0*(k-now))/(sum*1.0))+maxx;
printf("%d\n",ans);
}
}
}
return 0;
}