题目乱码。
题目链接: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;
}