链接:http://acm.hdu.edu.cn/showproblem.php?pid=4807
题意:一个n个点的,m条边的有向图,有k个学生在点0,他们要去点n-1,每条边的长度都是1,容量为w,现在问你,这k个学生最少要多少时间到n-1.
分析:很明显,时间最少肯定走最短路,但是每条边都有容量,所以有的学生走一条最短路的时候其他学生会去走其他的路,这些路都是不相交的,按照贪心策略我们走的时前k条不相交的最短路,费用流有个性质就是每次都会找到的最小费用就是且他们的流量是不相交的,就是我们要求的东西。
现在我们可以知道所有最短路了,它们需要的时间是递增的,开始贪心。
我们要求通过第x条路的时候,可以算出所有人通过前x条路的时间,然后去最小的时间。
计算过程:我们可以得到前x条每单位时间通过多少人(就是这些路的容量),时间=剩下的人/现在每单位时间通过的人数+当前道路时间
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 3010
#define Mm 20005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CLRS(a,b,Size) memset((a),(b),sizeof((a[0]))*(Size+1))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int dis[Mn],pre[Mn],head[Mn];
bool vis[Mn];
int tot;
struct edge {
int v,cap,next,cost;
} e[Mm];
void addedge(int u,int v,int w,int cost) {
e[tot].v=v;
e[tot].cap=w;
e[tot].cost=cost;
e[tot].next=head[u];
head[u]=tot++;
}
queue<int>q;
bool spfa(int s,int en) {
while(!q.empty()) q.pop();
for(int i=s ; i<=en; i++) {
dis[i]=INF;
vis[i]=false;
pre[i]=-1;
}
q.push(s);
dis[s]=0;
vis[s]=true;
while(!q.empty()) {
int u=q.front();
q.pop();
vis[u]=false;
for(int i=head[u]; i!=-1; i=e[i].next) {
int v=e[i].v;
int cost=e[i].cost;
if(e[i].cap&&dis[v]>dis[u]+cost) {
dis[v]=dis[u]+cost;
pre[v]=i;
if(!vis[v]) {
vis[v]=true;
q.push(v);
}
}
}
}
if(dis[en]==INF) return false;
return true;
}
int sum,bfTime,num,preSeNum;
void addmaxflow(int t) {
int maxflow=INF;
for(int i=pre[t]; i!=-1; i=pre[e[i^1].v]) maxflow=min(maxflow,e[i].cap);
for(int i=pre[t]; i!=-1; i=pre[e[i^1].v]) {
e[i].cap-=maxflow;
e[i^1].cap+=maxflow;
}
num=max(num-(dis[t]-bfTime)*preSeNum-maxflow,0);
preSeNum+=maxflow;
int needTime=dis[t]+(int)ceil(1.0*num/preSeNum);
sum=min(sum,needTime);
bfTime=dis[t];
}
void init() {
tot=0;
CLR(head,-1);
preSeNum=0;
sum=INF;
bfTime=0;
}
void get(int s,int t) {
while(spfa(s,t)) {
addmaxflow(t);
if(num==0) break;
}
if(sum==INF) printf("No solution\n");
else printf("%d\n",sum);
}
int main() {
int n,m,k;
while(~scanf("%d%d%d",&n,&m,&k)) {
init();
int s=0,t=n-1;
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w,1);
addedge(v,u,0,-1);
}
if(k==0) {
printf("0\n");
continue;
}
num=k;
get(s,t);
}
return 0;
}