POJ2455 Secret Milking Machine
Description
有
n
个点,
FJ要从点
v1
走到点
vn
走
k
次,每条边只能走一次。(他有一条用于从点
问最长那条路最短可以是多长?
Input
第一行:三个整数
n
、
接下来
Output
一个整数:最长那条图最短的长度。
题解
求最长的最短,二分啊。
每条边只走一次所以流量为一。
每次二分出一个答案 mid 。
跑网络流,只跑长度不大于 mid 的边。
看总流量是否为 k <script type="math/tex" id="MathJax-Element-34">k</script>。
code
#include<cstdio>
#include<cstdlib>
#include<string.h>
#include<algorithm>
#define oo 100000
using namespace std;
const int maxn=210;
const int maxp=500100;
int N,P,T;
struct EDGE
{
int ap,L,flow;
EDGE *next,*fe;
}edge[maxp],*ind[maxn];
int el=-1;
void input(int u,int v,int l,int flow)
{
edge[++el].ap=v;
edge[el].flow=flow;
edge[el].L=l;
edge[el].next=ind[u];
ind[u]=&edge[el];
edge[el].fe=&edge[el^1];
}
int level[maxn],q[maxn],Time=0;
bool bfs(int x)
{
int h1=1,t1=2;
q[1]=1;
level[1]=++Time;
while(h1<t1)
{
int u=q[h1];
for(EDGE *k=ind[u];k!=NULL;k=k->next)
{
int v=k->ap;
if(k->L>x||k->flow==0||level[v]>=level[1]) continue;
level[v]=level[u]+1;
Time=max(Time,level[v]);
if(v==N) return 1;
q[t1++]=v;
}
h1++;
}
return 0;
}
int dfs(int u,int flow,int x)
{
if(u==N) return flow;
int sum=0;
for(EDGE *k=ind[u];k!=NULL;k=k->next)
{
int v=k->ap;
if(k->L>x||k->flow==0||level[v]<=level[u]) continue;
int d=dfs(v,min(flow-sum,k->flow),x);
sum+=d;
k->flow-=d;
k->fe->flow+=d;
if(flow<=sum) break;
}
level[u]=0;
return sum;
}
bool check_dinic(int x)
{
int sum=0;
while(bfs(x))
sum+=dfs(1,oo,x);
return T<=sum ? 1 : 0;
}
void init()
{
for(int i=0;i<=el;i++) edge[i].flow=1;
}
int main()
{
int l=oo,r=0;
scanf("%d%d%d",&N,&P,&T);
for(int i=1;i<=P;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
r=max(r,z);
l=min(l,z);
input(x,y,z,1);
input(y,x,z,1);
}
while(l<r-1)
{
init();
int mid=(l+r)>>1;
if(check_dinic(mid)) r=mid;
else l=mid;
}
printf("%d",r);
return 0;
}