洛谷 P4014 分配问题 (费用流解决二分图最优匹配)

link

思路:用矩阵的行列建图,跑费用流即可,存个板子

#include 
#define ll long long
#define pi pair
#define mk make_pair
#define pb push_back
using namespace std;

const int maxn = 10005;
const int maxm = 1000005;
const int inf = 0x3f3f3f3f;

struct edges{
     
	int to,next,cap,flow,cost;
};

struct MCMF{
     
	int n;
	int cnt,head[maxn];
	int pre[maxn],d[maxn];
	int inq[maxn];
	edges edge[maxm];
	void init(int n)
	{
     
		this->n= n;
		this->cnt = 0;
		memset(head,-1,sizeof(head));
	}
	void ads(int u,int v,int cap,int cost){
     
		edge[cnt].to = v;
		edge[cnt].cap = cap;
		edge[cnt].cost = cost;
		edge[cnt].flow = 0;
		edge[cnt].next = head[u];
		head[u] = cnt++;
	}
	void AddEdge(int u,int v,int cap,int cost)
	{
     
		ads(u,v,cap,cost);
		ads(v,u,0,-cost);
	}
	bool spfa(int s,int t)
	{
     
		queue<int>q;
		for(int i=0;i<=n;i++)d[i] = inf,pre[i] = -1,inq[i] = 0;
		d[s] = 0;
		inq[s] = 1;
		q.push(s);
		while(q.size())
		{
     
			int u = q.front();
			q.pop();
			inq[u] = 0;
			for(int i=head[u];~i;i=edge[i].next)
			{
     
				int v = edge[i].to;
				if(edge[i].cap > edge[i].flow && d[v] > d[u] + edge[i].cost)
				{
     
					d[v] = d[u] + edge[i].cost;
					pre[v] = i;
					if(!inq[v])
					{
     
						inq[v] = 1;
						q.push(v);
					}
				}
			}
		}
		if(pre[t] == -1)return false;
		return true;
	}
	
	int mcmf(int s,int t)
	{
     
		int cost = 0;
		int flow = 0;
		while(spfa(s,t))
		{
     
			int mi = inf;
			for(int i=pre[t];~i;i = pre[edge[i^1].to])
			{
     
				if(mi > edge[i].cap-edge[i].flow)
				mi = edge[i].cap - edge[i].flow;
			}
			for(int i=pre[t];~i;i=pre[edge[i^1].to])
			{
     
				edge[i].flow += mi;
				edge[i^1].flow -= mi;
				cost += edge[i].cost * mi;
			}
			flow += mi;
		}
		return cost;
	}
	void clearflow()
	{
     
		for(int i=0;i<cnt;i++)
		edge[i].flow = 0,edge[i].cost = -edge[i].cost;
	}
}sol;
int main()
{
     
	int n;
	scanf("%d",&n);
	sol.init(n+n+3);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	{
     
		int x;
		scanf("%d",&x);
		sol.AddEdge(i,j+n,1,x);
	}
	int s = n+n+1,t=s+1;
	for(int i=1;i<=n;i++)
	{
     
		sol.AddEdge(s,i,1,0);
		sol.AddEdge(i+n,t,1,0);
	}
	printf("%d\n",sol.mcmf(s,t));
	sol.clearflow();
	printf("%d\n",-sol.mcmf(s,t));
	
	return 0;
}

你可能感兴趣的:(图------网络流)