• P1559 运动员最佳匹配问题 最大费用最大流


    P1559 运动员最佳匹配问题 费用流

    题目链接

    ​ 虽然思想不难, 但是写了好久, 原因是网络流都忘得差不多了, 这相当于复习了.

    ​ 最大费用最大流.

    ​ 炒鸡源点向男生连一条费用为0, 流量为1的边.女生向炒鸡汇点连一条费用为0,流量为1的边.所有男生向女生连一条费用为(p[i][j] * q[j][i]), 流量为1的边.

    ​ 流量都为1可以确保一个男生对应一个女生.思想挺简单的.

    #include <bits/stdc++.h>
    
    using namespace std;
    
    inline long long read() {
    	long long s = 0, f = 1; char ch;
    	while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    	for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    	return s * f;
    }
    
    const int N = 25;
    int n, s, t, ans, cnt;
    int in[N], dis[N], pre[N], incf[N], head[N], p[N][N], q[N][N];
    struct edge { int to, nxt, val, cost; } e[N * N + 2 * N]; 
    
    void add(int x, int y, int z, int f) {
    	e[++ cnt].nxt = head[x]; head[x] = cnt; e[cnt].to = y; e[cnt].val = z; e[cnt].cost = f;
    }
    
    int spfa() {
    	queue <int> q;
    	for(int i = 0;i <= t; i++) dis[i] = -1e9;
    	q.push(s); dis[s] = 0; in[s] = 1; incf[0] = 1e9;
    	while(!q.empty()) {
    		int x = q.front(); q.pop(); in[x] = 0;
    		for(int i = head[x]; i ; i = e[i].nxt) {
    			if(!e[i].val) continue;
    			int y = e[i].to; 
    			if(dis[y] < dis[x] + e[i].cost) {
    				dis[y] = dis[x] + e[i].cost; pre[y] = i;
    				incf[y] = min(incf[x], e[i].val);
    				if(!in[y]) in[y] = 1, q.push(y);
    			}
    		}
    	}
    	return dis[t] != -1e9;
    }
    
    void up() {
    	int p = t;
    	while(p != s) {
    		int i = pre[p];
    		e[i].val -= incf[t]; e[i ^ 1].val += incf[t];
    		p = e[i ^ 1].to;
    		ans += e[i].cost * incf[t];
    	}
    }
    
    int main() {
    
    	n = read(); s = 0, t = 2 * n + 1; cnt = 1;
    	for(int i = 1;i <= n; i++) for(int j = 1;j <= n; j++) p[i][j] = read();
    	for(int i = 1;i <= n; i++) for(int j = 1;j <= n; j++) q[i][j] = read();
    	for(int i = 1;i <= n; i++) add(s, i, 1, 0), add(i, s, 0, 0);
    	for(int i = n + 1;i <= 2 * n; i++) add(i, t, 1, 0), add(t, i, 0, 0);
    	for(int i = 1;i <= n; i++) 
    		for(int j = 1;j <= n; j++) add(i, j + n, 1, p[i][j] * q[j][i]), add(j + n, i, 0, -p[i][j] * q[j][i]);
    	while(spfa()) up();
    	printf("%d", ans);
    
    	return 0;
    }
    
  • 相关阅读:
    使用express+mongoDB搭建多人博客 学习(6)发表文章
    [译]Understanding ECMAScript6 对象
    select的type属性
    jQuery addClass() 源码解读
    jQuery val()方法及valHooks源码解读
    mpvue使用scroll-view实现图片横向滑动
    mpvue图片轮播遇到的问题
    mpvue小程序图片404
    js截取字符串的后几位数
    jQuery WeUI实现分页功能
  • 原文地址:https://www.cnblogs.com/czhui666/p/13974670.html
Copyright © 2020-2023  润新知