题目链接:1834:[ZJOI2010]network 网络扩容
好端端的一道水题让我给做的……
一开始我想的是先跑一边dinic得到残量网络,反正K不大然后就跑K遍费用流,每次跑费用流时碰到一条正向边没流满就把边权设为0,否则流量+1,边权为最开始的权值
但是这样傻X都能看出来是错的QAQ
加入跑了一遍费用流以后我们流量加过1的边并没有流到,那么他的权值就成0了,成0了,成0了……然后就GG了……
我还满心欢喜的写了半天,错了还以为是模板打错了QAQ
荏弱没话说……
这题我们一遍dinic后对于剩余图,只要这张图上的边是正边就复制一条容量为inf费用不变,反向边复制一条容量为0费用相反,并把原来的边的边权改为0
注意是复制原来的边保留,这样再次跑的时候由于原来的剩余边费用都为0会被优先选择
于是就对了……我还是太naive……
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=2000+10;
const int inf=0x7fffffff/2-1;
int n,m,h[maxn],tot=1,S,T,K,vis[maxn];
struct edge{int to,next,w,c,f;}G[maxn*10];
int dis[maxn],pre[maxn],cur[maxn];
bool bfs(){
for (int i=S;i<=T;++i) vis[i]=-1;
queue<int>q; q.push(S); vis[S]=0;
while (!q.empty()){
int u=q.front(); q.pop();
for (int i=h[u];i;i=G[i].next){
int v=G[i].to;
if (vis[v]==-1&&G[i].c>0){
vis[v]=vis[u]+1; q.push(v);
}
}
}return vis[T]!=-1;
}
int dfs(int x,int f){
if (x==T||f==0) return f;
int w,used=0;
for (int i=cur[x];i;i=G[i].next)
if (G[i].c&&vis[x]+1==vis[G[i].to]){
w=f-used;
w=dfs(G[i].to,min(w,G[i].c));
G[i].c-=w; G[i^1].c+=w;
used+=w; if (used==f) return f;
if (G[i].c) cur[x]=i;
}
if (!used) vis[x]=-1;
return used;
}
void dinic(){
int ret=0;
while (bfs()){
for (int i=S;i<=T;++i) cur[i]=h[i];
ret+=dfs(S,inf);
}printf("%d ",ret);
}
void add(int x,int y,int c,int w){
G[++tot].to=y; G[tot].next=h[x]; h[x]=tot;
G[tot].c=c; G[tot].w=w; G[tot].f=x;
}
void rebuild(){
int sum=tot; S=0; add(S,1,K,0); add(1,S,0,0);
for (int i=2;i<=sum;++i)
if (!(i&1)) add(G[i].f,G[i].to,inf,G[i].w),
add(G[i].to,G[i].f,0,-G[i].w),
G[i].w=G[i^1].w=0;
}
bool spfa(){
for (int i=S;i<=T;++i){vis[i]=0;dis[i]=inf;pre[i]=-1;}
vis[S]=1; dis[S]=0; deque<int>q; q.push_front(S);
while (!q.empty()){
int u=q.front(); q.pop_front(); vis[u]=0;
for (int i=h[u];i;i=G[i].next){
int v=G[i].to;
if (dis[v]>dis[u]+G[i].w&&G[i].c>0){
dis[v]=dis[u]+G[i].w;
pre[v]=i; if (!vis[v]){ vis[v]=1;
if (!q.empty()&&dis[v]<dis[q.front()])
q.push_front(v);
else q.push_back(v);
}
}
}
}return pre[T]!=-1;
}
void min_cost_flow(){
int cost=0;
while (spfa()){
int mf=inf;
for (int i=pre[T];i!=-1;i=pre[G[i^1].to])
mf=min(mf,G[i].c);
for (int i=pre[T];i!=-1;i=pre[G[i^1].to])
{G[i].c-=mf;G[i^1].c+=mf;cost+=G[i].w*mf;}
}printf("%d",cost);
}
int main(){
scanf("%d%d%d",&n,&m,&K); S=1; T=n;
for (int i=1;i<=m;++i){
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
add(a,b,c,d); add(b,a,0,-d);
}
dinic(); rebuild();
min_cost_flow();
}