【问题描述】
宇宙中有n个星球,你的任务是用最短的时间把k个超级计算机从星球S运送到T,每个超级计算机需要一整艘飞船来运输。行星之间有m条双向隧道,每条隧道需要一天时间来通过,且不能有两艘飞船同时使用一条隧道。隧道不会连接两个不同的行星,且每一对行星之间最多只有一条通道。隧道不会连接两个相同的行星,且每一对行星之间最多只有一条隧道。
【输入格式】
第一行包含5个正整数n,m,k,S,T(S!=T)。接下来的m行,每行包含两个不同的整数u和v,表示行星u和v之间有一条隧道。注意,隧道时双向的,但每一天只有一艘飞船能穿过一条隧道。另外,两艘飞船不能同时沿着相反的方向穿过同一个隧道。
【输出格式】
输出一行,为最少需要的天数day。注意:所有的数据中,答案day不会超过100。
【输入样例】
【样例1】
4 3 2 1 4
1 2
2 3
3 4
【样例2】
4 4 3 1 4
1 2
1 3
3 4
2 4
【输出样例】
【样例1】
4
【样例2】
3
【数据范围】
n <= 150,m <= 400, k <= 50
【来源】
uva 1324
这是一道比较复杂的最大流的题了。对于网络流我们首先想到的还是应该找源点和汇点,这里的汇点明显需要认为创造超级汇点(每天的终点都要指向汇点)。
对于这道题,我这里采取了一天一天加图的方法。(这样可以利用前面的直接加点后继续流就可以了)。
把每个点分成若干个点第i*n个点表示第n个点在第i天的对应点。然后每加一天多一层结点,加边就可以了。这里要注意每个点都可以走向同一个点的对应的下一天的点。
详细代码如下:
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn=15005;
const int inf=20000005;
struct edge
{
int u,v,cap,flow;
}b[405];
vector<edge>e;
vector<int>g[maxn];
int n,m,s,t,num,a[maxn],fa[maxn],q[maxn*10],cnt=-1,S,T,flow=0;
void add(int x,int y,int c)
{
e.push_back((edge){x,y,c,0});
g[x].push_back(++cnt);
e.push_back((edge){y,x,0,0});
g[y].push_back(++cnt);
}
void work(int tt)
{
for(int i=1;i<=n;i++) add((tt-1)*n+i,tt*n+i,inf);
for(int i=1;i<=m;i++)
{
add(b[i].u+(tt-1)*n,tt*n+b[i].v,1);
add(b[i].v+(tt-1)*n,tt*n+b[i].u,1);
}
add(t+tt*n,T,inf);
}
int bfs()
{
int root=0,frond=0;
memset(fa,0,sizeof(fa));
memset(a,0,sizeof(a));
q[root++]=S;
a[S]=inf;
fa[S]=-1;
while(root!=frond)
{
int i=q[frond++];
int tt=g[i].size();
for(int k=0;k<tt;k++)
{
int id=g[i][k],j=e[id].v;
if(a[j]||e[id].flow>=e[id].cap) continue;
a[j]=min(a[i],e[id].cap-e[id].flow);
fa[j]=id;
q[root++]=j;
if(j==T) return a[T];
}
}
return -1;
}
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d%d%d%d%d",&n,&m,&num,&s,&t);
for(int i=1;i<=m;i++) scanf("%d%d",&b[i].u,&b[i].v);
S=0,T=n*100+1;
add(S,s,inf);add(t,T,inf);
int i=1;
for(;i<=100;i++)
{
work(i);
while(1)
{
int delt=bfs();
if(delt==-1) break;
flow+=delt;
int id=fa[T];
while(id!=-1)
{
e[id].flow+=delt;
e[id^1].flow-=delt;
id=fa[e[id].u];
}
}
if(flow>=num) break;
}
printf("%d",i);
return 0;
}