BZOJ 1834 [ZJOI2010]network 网络扩容
题目链接:http://www.zybbs.org/JudgeOnline/problem.php?id=1834
题目大意:给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。
第一问很好写,按原流量0费用建边,最大流随便一搞就行,第二问也挺好写,在原来边的基础上另加一条无限流量原费用的边,和一个与原源点相连流量为k,费用为0的新汇点,费用流搞一下就好了。
代码:
View Code
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
#define MaxN 1010
#define MaxM 5010
#define INF 2000000
struct atp
{
int x,y,flow,cost,op,next;
}e[MaxM*4];int first[MaxN];
struct Bian
{
int x,y,flow,cost;
}bian[MaxM];
int n,m,InsFlow,tot=0,MaxFlow=0,MinCost=0,s,t;
int h[MaxN],num[MaxN];
int d[MaxN],pre[MaxN]; bool b[MaxN];
void add(int x,int y,int flow,int cost)
{
tot++;
e[tot].y=y;
e[tot].x=x;
e[tot].flow=flow;
e[tot].cost=cost;
e[tot].op=tot+1;
e[tot].next=first[x];
first[x]=tot;
tot++;
e[tot].y=x;
e[tot].x=y;
e[tot].flow=0;
e[tot].cost=-cost;
e[tot].op=tot-1;
e[tot].next=first[y];
first[y]=tot;
}
void init()
{
scanf("%d%d%d",&n,&m,&InsFlow);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&bian[i].x,&bian[i].y,&bian[i].flow,&bian[i].cost);
add(bian[i].x,bian[i].y,bian[i].flow,0);
}
s=1,t=n;
}
int find(int u,int flow)
{
if (u==t) return flow;
int temp=flow,pos=n-1;
for (int p=first[u];p;p=e[p].next)
{
if (h[u]==h[e[p].y]+1 && e[p].flow>0)
{
int f=find(e[p].y,min(e[p].flow,temp));
temp-=f;
e[p].flow-=f;
e[e[p].op].flow+=f;
if (temp==0 || h[s]==n) return flow-temp;
}
if (e[p].flow>0 && pos>h[e[p].y]) pos=h[e[p].y];
}
if (temp==flow)
{
num[h[u]]--;
if (num[h[u]]==0) h[s]=n;
else
{
h[u]=pos+1;
num[h[u]]++;
}
}
return flow-temp;
}
bool SPFA()
{
queue<int>q;
int u,Maxt;
while (!q.empty()) q.pop();
memset(b,false,sizeof(b));
memset(d,100,sizeof(d));
Maxt=d[0];
pre[0]=-1;
q.push(s);b[s]=true;d[s]=0;
while (!q.empty())
{
u=q.front();q.pop();
for (int p=first[u];p;p=e[p].next)
{
if (d[u]+e[p].cost<d[e[p].y] && e[p].flow)
{
d[e[p].y]=d[u]+e[p].cost;
pre[e[p].y]=p;
if (!b[e[p].y])
{
b[e[p].y]=true;
q.push(e[p].y);
}
}
}
b[u]=false;
}
if (d[t]<Maxt) return true; else return false;
}
void update()
{
int Min=INF,p;
for (p=pre[t];p!=-1;p=pre[e[p].x])
Min=min(Min,e[p].flow);
for (p=pre[t];p!=-1;p=pre[e[p].x])
e[p].flow-=Min,MinCost+=Min*e[p].cost;
}
int main()
{
freopen("in","r",stdin);
freopen("out","w",stdout);
init();
while (h[s]<n) MaxFlow+=find(s,INF);printf("%d ",MaxFlow);
for (int i=1;i<=m;i++)
add(bian[i].x,bian[i].y,INF,bian[i].cost);
add(0,1,InsFlow,0);
s=0;
while (SPFA()) update();printf("%d",MinCost);
}