地震逃生【网络流】
##题目大意:
有个人要从到,每条路最多能过个人,求每次最多能过几个人,需要几次才能使全部人通过?
##思路:
很裸的最大流。源点连向点,点连向汇点,按照读入的数据建模,跑一边即可。
##代码:
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#define Inf 0x7f
#define INF 2147483647
using namespace std;
int n,m,peo,k,head[100001],dep[1001],x,y,z,ans,sum,s,t;
struct edge
{
int next,to,c;
}e[100001];
void add(int from,int to,int c) //建模
{
k++;
e[k].c=c;
e[k].to=to;
e[k].next=head[from];
head[from]=k;
}
bool bfs() //分层
{
memset(dep,0x3f,sizeof(dep));
dep[s]=0;
queue<int> q;
q.push(s);
while (q.size())
{
int u=q.front();
q.pop();
for (int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if (dep[v]>dep[u]+1&&e[i].c)
{
dep[v]=dep[u]+1;
q.push(v);
}
}
}
return (dep[t]<0x3f3f3f3f);
}
int dfs(int u,int low) //找增广路
{
int lows=0;
if (u==t) return low;
for (int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if (dep[v]==dep[u]+1&&e[i].c)
{
lows=dfs(v,min(low,e[i].c)); //找最小流量
if (!lows) continue;
e[i].c-=lows; //正向边
e[i^1].c+=lows; //反向边
return lows;
}
}
return 0;
}
int main()
{
scanf("%d%d%d",&n,&m,&peo);
k=1;
s=999;
t=998;
add(s,1,INF);
add(1,s,0);
add(n,t,INF);
add(t,n,0);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,0);
}
while (bfs())
{
while (sum=dfs(s,INF))
ans+=sum;
}
if (!ans) return printf("Orz Ni Jinan Saint Cow!")&0;
if (peo%ans) printf("%d %d",ans,peo/ans+1);
else printf("%d %d",ans,peo/ans);
return 0;
}