最大费用最大流
- 最大求法:
- 将所有费用取反
- 求最小费用,再取反0
cpp
int h[N],e[M],f[M],w[M],ne[M],idx;
int dis[N],cur[N];//d表示最短距离,cur为当前弧
int n,m,S,T;
bool vis[N];
int height[N];// 势能函数
vector<int> dot;// 点数
void add(int a,int b,int c,int d){
e[idx]=b,f[idx]=c,w[idx]=d,ne[idx]=h[a],h[a]=idx++;
e[idx]=a,f[idx]=0,w[idx]=-d,ne[idx]=h[b],h[b]=idx++;
}
bool dijk(){
for(auto &i:dot)dis[i]=INF,cur[i]=h[i];
priority_queue<PII,vector<PII>,greater<>> pq;
dis[S]=0;
pq.emplace(0,S);
while(!pq.empty()){
auto [d,u]=pq.top();
pq.pop();
if(dis[u]!=d)continue;
for(int i=h[u];~i;i=ne[i]){
int v=e[i];
if(f[i]&&dis[v]>d+height[u]-height[v]+w[i]){
dis[v]=d+height[u]-height[v]+w[i];
pq.emplace(dis[v],v);
}
}
}
return dis[T]!=INF;
}
int find(int u,int limit){
if(!limit||u==T)return limit;
int flow=0;
vis[u]=1;
for(int &i=cur[u];~i&&flow<limit;i=ne[i]){
int v=e[i];
if(dis[v]==dis[u]+height[u]-height[v]+w[i]&&f[i]&&!vis[v]){
int t=find(v,min(f[i],limit-flow));
f[i]-=t,f[i^1]+=t,flow+=t;
if(flow==limit)break;
}
}
vis[u]=0;
return flow;
}
void mcmf(int &flow,int &cost){
flow=cost=0;
int r;
while(dijk()){
int r=find(S,INF);
flow+=r;
for(auto &i:dot)height[i]+=dis[i];
cost+=height[T]*r;
}
}
void solve(){
cin>>m>>n;
S=0,T=n+m+1;
for(int i=0;i<=n+m+1;i++)dot.push_back(i);
memset(h,-1,sizeof h);
for(int i=1;i<=m;i++){
int x;
cin>>x;
add(S,i,x,0);
}
for(int i=1;i<=n;i++){
int x;
cin>>x;
add(m+i,T,x,0);
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
int c;
cin>>c;
add(i,m+j,INF,c);
}
}
int flow,cost;
mcmf(flow,cost);
cout<<cost<<"\n";
for(int i=0;i<idx;i+=2){
f[i]+=f[i^1],f[i^1]=0;
w[i]=-w[i],w[i^1]=-w[i^1];
}
mcmf(flow,cost);
cout<<-cost;
}