您的位置:首页 > 理论基础 > 计算机网络

nefu500网购【二分+网络流】

2016-04-17 10:56 453 查看

Problem:500

Time Limit:3000ms

Memory Limit:65536K

Description

在这个信息化的时代,网购成为了最流行的购物方式,比起在大街上,顶着烈日寻找需要的商品,大多数人更愿意坐在家里,点击下鼠标,来找到喜欢的商品,并完成购物。尽管网购还有很多安全问题,但是接受网购的人还是越来越多。网购的轻松,使得许多人淡忘了货物配送的烦恼。其实货物配送才是网购最重要的环节,货物送不到,一切都免谈。货物的配送还耗费了大量的资金,很多时候,一件商品被买下了,那么它可能要经过多城市,才能送达目的地。Pira作为配送商品的管理人员,他希望在满足所有货物能送达目的地的条件下,使得每次完成两个城市间的配送所花费的运费的最大值最小,也就是使得所走的路线中,费用最大的那条边的值最小
PS:老板看到最大的一次花费太大的话,你就等着被fire吧T_T


Input

多组数据输入.
每组输入第一行有两个整数n和m,n表示有n个城市,m表示有m条路线,所有货物都是从1号城市配送的(1<=n<=10000,1<=m<=100000)
第二行有n个数,表示编号为1~n的城市,所购的物品个数,所有物品数的和小于10000000
接下来m行,每行有四个数u,v,cost和cap,表示从城市u到城市v配送一件物品需花费cost,最多可配送cap件物品,注意所有边都是单向的(1<=u,v<=n,0< cost< 10000000,0<=cap< 100000)


Output

每组输出每次完成城市间运输的最小花费,即最小的边权限制,如果不能完成货物的配送,则输出-1。


Sample Input

3 3
0 0 2
1 2 2 1
2 3 1 1
1 3 3 1
3 3
0 0 1
1 2 2 1
2 3 5 1
1 3 4 1


Sample Output

3
4


Hint

并不是求花费的总和


Source

Pira


之前做的二分+可行解都就饭吃了→_→做uva11478 Halum【二分+差分约束】没想到二分找满足差分约束最小值也就罢了,做UVA
- 11090 Going in Cycle!! 【Bellman-Ford算法判负环 二分】依旧想不到==,背景换成了网络流又不会了==

记得nefu488餐巾计划问题【网络流24题】最小费用流十分纠结于费用建边的时候为什么不考虑流量,这个题也不考虑流量,直接限制cost数组就够了~二分查找上下界,最大流==满流量即可

比较纠结的是为什么最小值边界不能用数组中的最小值??

#include <iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
const int mm=220005;
const int mn=22222;
const int oo=1000000000;
int node,src,dest,edge;
int reach[mm],flow[mm],nxt[mm];
int head[mn],work[mn],dis[mn],q[mn];
inline int min(int a,int b)
{
return a<b?a:b;
}
inline void prepare(int _node,int _src,int _dest)
{
node=_node,src=_src,dest=_dest;
memset(head,-1,sizeof(head));
edge=0;
}
inline void addedge(int u,int v,int c1)
{
reach[edge]=v,flow[edge]=c1,nxt[edge]=head[u],head[u]=edge++;
reach[edge]=u,flow[edge]=0,nxt[edge]=head[v],head[v]=edge++;
}
bool Dinic_bfs()
{
int i,u,v,l,r=0;
for(i=0;i<node;++i)dis[i]=-1;
dis[q[r++]=src]=0;
for(l=0;l<r;++l)
for(i=head[u=q[l]];i>=0;i=nxt[i])
if(flow[i]&&dis[v=reach[i]]<0)
{
dis[q[r++]=v]=dis[u]+1;
if(v==dest)return 1;
}
return 0;
}
int Dinic_dfs(int u,int exp)
{
if(u==dest)return exp;
for(int &i=work[u],v,tmp;i>=0;i=nxt[i])
if(flow[i]&&dis[v=reach[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)
{
flow[i]-=tmp;
flow[i^1]+=tmp;
return tmp;
}dis[u]--;
return 0;
}
int Dinic_flow()
{
int i,ret=0,delta;
while(Dinic_bfs())
{
for(i=0;i<node;++i)work[i]=head[i];
while(delta=Dinic_dfs(src,oo))ret+=delta;
}
return ret;
}
int sum,need[mn],cost[mm],cap[mm],uu[mm],vv[mm];
int n,m;
bool judge(int value)
{
prepare(n+2,0,n+1);
for(int i=1;i<=m;i++)
if(cost[i]<=value)
addedge(uu[i],vv[i],cap[i]);
addedge(src,1,sum);
for(int i=1;i<=n;i++) addedge(i,dest,need[i]);
if(sum==Dinic_flow()) return true;
return false;
}
int main()
{
// freopen("cin.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
sum=0;
for(int i=1;i<=n;i++){
scanf("%d",&need[i]);
sum+=need[i];
}
int maxcost=0;
int mincost=10000001;
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&uu[i],&vv[i],&cost[i],&cap[i]);
if(cost[i]>maxcost) maxcost=cost[i];
if(cost[i]<mincost) mincost=cost[i];
}
int l=0,r=maxcost+1,mid,ans;
bool flag=0;
while(l<=r)
{
mid=(r+l)/2;
if(judge(mid)) {ans=mid;r=mid-1;flag=1;}
else l=mid+1;
}
if(!flag) puts("-1");
else printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: