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

[BZOJ1834][ZJOI2010]network 网络扩容(最大流+费用流)

2016-04-28 15:13 561 查看

题目描述

传送门

题解

Q1 傻逼最大流

Q2 求出最大流之后将图暴力重构,原图中的边费用为0,流量为初始流量,添加一些和原图边同始同终的边,费用为扩容费用,流量为INF,再添加一个超级源连向原先的源点,费用为0,流量为k+maxflow来限流,求最小费用流即可。

思路如此简单我这个傻逼刚开始想错了,,,Orz ATP

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;

const int max_n=1e3+5;
const int max_m=5e4+5;
const int max_e=max_m*2;
const int INF=1e9;

int n,m,k,cap,maxflow,mincost;
int tot,point[max_n],next[max_e],v[max_e],remain[max_e],c[max_e];
int deep[max_n],cur[max_n],last[max_n],num[max_n],dis[max_n];
bool vis[max_n];
struct hp{int x,y,cap,w;}edge[max_m];
queue <int> q;

inline void addedge(int x,int y,int cap,int z){
++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=cap; c[tot]=z;
++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0; c[tot]=-z;
}

inline void bfs(int t){
for (int i=1;i<=n;++i) deep[i]=n; deep[t]=0;
while (!q.empty()) q.pop(); q.push(t);
while (!q.empty()){
int now=q.front(); q.pop();
for (int i=point[now];i!=-1;i=next[i])
if (deep[v[i]]==n&&remain[i^1]){
deep[v[i]]=deep[now]+1;
q.push(v[i]);
}
}
}
inline int addflow(int s,int t){
int now=t,ans=INF;
while (now!=s){
ans=min(ans,remain[last[now]]);
now=v[last[now]^1];
}
now=t;
while (now!=s){
remain[last[now]]-=ans;
remain[last[now]^1]+=ans;
now=v[last[now]^1];
}
return ans;
}
inline void isap(int s,int t){
bfs(t);
for (int i=1;i<=n;++i) ++num[deep[i]];
for (int i=1;i<=n;++i) cur[i]=point[i];

int now=s;
while (deep[s]<n){
if (now==t){
maxflow+=addflow(s,t);
now=s;
}

bool has_find=false;
for (int i=cur[now];i!=-1;i=next[i])
if (deep[v[i]]+1==deep[now]&&remain[i]){
has_find=true;
cur[now]=i;
last[v[i]]=i;
now=v[i];
break;
}

if (!has_find){
int minn=n-1;
for (int i=point[now];i!=-1;i=next[i])
if (remain[i]) minn=min(minn,deep[v[i]]);
if (!(--num[deep[now]])) break;
num[deep[now]=minn+1]++;
cur[now]=point[now];
if (now!=s) now=v[last[now]^1];
}
}
}
inline bool bfs(int s,int t){
memset(dis,0x7f,sizeof(dis)); dis[n+1]=0;
memset(vis,0,sizeof(vis)); vis[n+1]=true;
while (!q.empty()) q.pop(); q.push(n+1);
while (!q.empty()){
int now=q.front(); q.pop();
vis[now]=false;
for (int i=point[now];i!=-1;i=next[i])
if (dis[v[i]]>dis[now]+c[i]&&remain[i]){
dis[v[i]]=dis[now]+c[i];
last[v[i]]=i;
if (!vis[v[i]]){
vis[v[i]]=true;
q.push(v[i]);
}
}
}
if (dis[t]>INF) return false;
int flow=addflow(s,t);
mincost+=dis[t]*flow;
return true;
}
inline void min_cost_flow(int s,int t){
mincost=0;
while (bfs(s,t));
}
inline void rebuild(){
tot=-1;
memset(point,-1,sizeof(point));
memset(next,-1,sizeof(next));
for (int i=1;i<=m;++i){
addedge(edge[i].x,edge[i].y,edge[i].cap,0);
addedge(edge[i].x,edge[i].y,INF,edge[i].w);
}
addedge(n+1,1,maxflow+k,0);
min_cost_flow(n+1,n);
}
int main(){
scanf("%d%d%d",&n,&m,&k);
tot=-1;
memset(next,-1,sizeof(next));
memset(point,-1,sizeof(point));
for (int i=1;i<=m;++i){
scanf("%d%d%d%d",&edge[i].x,&edge[i].y,&edge[i].cap,&edge[i].w);
addedge(edge[i].x,edge[i].y,edge[i].cap,0);
}
isap(1,n);
printf("%d ",maxflow);
rebuild();
printf("%d\n",mincost);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: