Pira
题意:问的是最小花费,最小边权限制,就是一次一次的运送货物,当把所有货物运送完毕后,看看在这k次运输中哪次运费最多;我们不能把内次运送费用都求出来,我们的策略是利用二分思想求最小的费用,即每次定一个费用去完成这项任务(就是把所有城市的货物都能够运送到),能完成的话向下找,不能完成向上找,最终找到一个最小的费用,在这个费用下,可以完成运送任务;
二分时,l=0,r=最大费用+1,题目数据很强,tle了多次,wa了多次;
具体看代码:
#include <iostream>
#include <string.h>
#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
const int MAXN=100110,maxn=100110;
const int MAXM=4000110,maxm=4000110;
const int INF=0x3f3f3f3f,inf=0x3f3f3f3f;
struct Node
{
int to,next,cap;
}edge[MAXM];
int tol;int head[MAXN];
int gap[MAXN],dis[MAXN],pre[MAXN],cur[MAXN];
void init()
{
tol=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
edge[tol].to=v;edge[tol].cap=w;edge[tol].next=head[u];head[u]=tol++;
edge[tol].to=u;edge[tol].cap=rw;edge[tol].next=head[v];head[v]=tol++;
}
int sap(int start,int endw,int nodenum)
{
memset(dis,0,sizeof(dis));
memset(gap,0,sizeof(gap));
memcpy(cur,head,sizeof(head));
int u=pre[start]=start,maxflow=0,aug=-1;
gap[0]=nodenum;
while(dis[start]<nodenum)
{
loop:
for(int &i=cur[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap&&dis[u]==dis[v]+1)
{
if(aug==-1||aug>edge[i].cap)
aug=edge[i].cap;
pre[v]=u;
u=v;
if(v==endw)
{
maxflow+=aug;
for(u=pre[u];v!=start;v=u,u=pre[u])
{
edge[cur[u]].cap-=aug;
edge[cur[u]^1].cap+=aug;
}
aug=-1;
}
goto loop;
}
}
int mindis=nodenum;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap&&mindis>dis[v])
{
cur[u]=i;
mindis=dis[v];
}
}
if((--gap[dis[u]])==0)break;
gap[dis[u]=mindis+1]++;
u=pre[u];
}
return maxflow;
}
int num[maxn];
struct p
{
int u,v,cap,flow;
}Q[maxn];
int main()
{
int n,sum,m;
int S,T;
int l,r,mid;
while(scanf("%d%d",&n,&m)!=-1)
{
sum=0;
T=n+1;
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
sum+=num[i];
}
l=0,r=0;
for(int i=0;i<m;i++)
{
scanf("%d%d%d%d",&Q[i].u,&Q[i].v,&Q[i].cap,&Q[i].flow);
r=max(r,Q[i].cap);
}
int ans=inf;
r++;
while(l<=r)
{
mid=(l+r)/2;
init();
for(int i=0;i<m;i++)
{
if(Q[i].cap<=mid)
addedge(Q[i].u,Q[i].v,Q[i].flow);
}
for(int i=1;i<=n;i++)
if(num[i])
addedge(i,T,num[i]);
if(sap(1,T,T+1)==sum)
{
r=mid-1;
ans=min(ans,mid);
}
else
l=mid+1;
}
if(ans==inf)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}
<br /><span id="_xhe_temp" width="0" height="0"><br /></span>
<br />
<br />