题目乱码。
题目链接:P 4015
费用流的模板题。。。。。直接按照题目建边跑一遍费用流即可(这居然是网络流24题。。。。),需要注意跑完一次网络流之后,要回归原图跑第二次。
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=410,M=100010;
const int inf=0x3f3f3f3f3f3f3f3f;
int n,m,s,t,d[N],a[N],b[N],c[N][N];
int head[N],nex[M],to[M],w[M],flow[M],tot=1;
struct node{
int v,e;
}p[N];
inline void ade(int a,int b,int c,int d){
to[++tot]=b; w[tot]=d; flow[tot]=c; nex[tot]=head[a]; head[a]=tot;
}
inline void add(int a,int b,int c,int d){
ade(a,b,c,d); ade(b,a,0,-d);
}
int spfa(int k){
queue<int> q; int vis[N]={0}; q.push(s); vis[s]=1;
if(k) memset(d,0xcf,sizeof d);
else memset(d,0x3f,sizeof d); d[s]=0;
while(q.size()){
int u=q.front(); q.pop(); vis[u]=0;
for(int i=head[u];i;i=nex[i]){
if(k){
if(flow[i]&&d[to[i]]<d[u]+w[i]){
d[to[i]]=d[u]+w[i];
p[to[i]].v=u; p[to[i]].e=i;
if(!vis[to[i]]) q.push(to[i]),vis[to[i]]=1;
}
}else{
if(flow[i]&&d[to[i]]>d[u]+w[i]){
d[to[i]]=d[u]+w[i];
p[to[i]].v=u; p[to[i]].e=i;
if(!vis[to[i]]) q.push(to[i]),vis[to[i]]=1;
}
}
}
}
if(k) return d[t]!=0xcfcfcfcfcfcfcfcf;
else return d[t]!=inf;
}
int EK(int k){
int res=0;
while(spfa(k)){
int mi=inf;
for(int i=t;i!=s;i=p[i].v) mi=min(mi,flow[p[i].e]);
for(int i=t;i!=s;i=p[i].v){
flow[p[i].e]-=mi; flow[p[i].e^1]+=mi;
}
res+=mi*d[t];
}
return res;
}
signed main(){
cin>>m>>n; s=0; t=n+m+1;
for(int i=1;i<=m;i++){
cin>>a[i]; add(s,i,a[i],0);
}
for(int i=1;i<=n;i++){
cin>>b[i]; add(i+m,t,b[i],0);
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
cin>>c[i][j]; add(i,m+j,inf,c[i][j]);
}
}
cout<<EK(0)<<endl; tot=1; memset(head,0,sizeof head);
for(int i=1;i<=m;i++){
add(s,i,a[i],0);
}
for(int i=1;i<=n;i++){
add(i+m,t,b[i],0);
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
add(i,m+j,inf,c[i][j]);
}
}
cout<<EK(1)<<endl;
return 0;
}