Poj 1459 Power Network

题意:给几个发电站,给几个消耗站,再给几个转发点。发电站只发电,消耗站只消耗电,转发点只是转发电,给出各个传送线的传电能力,求消耗站能获得的最多电是多少。

思路:增加一个超级源点,和超级汇点,转化成最大流问题求解。

#include <cstdio>
#include <memory.h>
#include <iostream>
using namespace std;

const int MAX = 1024;

int n;                // X的大小
int weight [MAX] [MAX];        // X到Y的映射(权重)
int lx [MAX], ly [MAX];        // 标号
bool sx [MAX], sy [MAX];    // 是否被搜索过
int match [MAX];        // Y(i)与X(match [i])匹配

// 初始化权重
void init (int size);
//从X(u)出发寻找增广路径,存在则返回true
bool path (int u);
// 参数maxsum为true,则返回最大权匹配,否则返回最小权匹配
int bestmatch (bool maxsum = true);
int min(int a,int b) {
	if ( a<b )
		return a;
	return b;
}
void init (int size)
{
	int i,j;
    n = size;
    for (i = 0; i < n; i ++)
        for (j = 0; j < n; j ++)
            scanf ("%d", &weight [i] [j]);
}
bool path (int u)
{
    sx [u] = true;
	int v;
    for (v = 0; v < n; v ++)
        if (!sy [v] && lx[u] + ly [v] == weight [u] [v]) {
            sy [v] = true;
            if (match [v] == -1 || path (match [v])) {
                match [v] = u;
                return true;
			}
		}
    return false;
}

int bestmatch (bool maxsum)
{
    int i, j;
    if (!maxsum) {
        for (i = 0; i < n; i ++)
            for (j = 0; j < n; j ++)
                weight [i] [j] = -weight [i] [j];
	}

    // 初始化标号
    for (i = 0; i < n; i ++) {
        lx [i] = -0x1FFFFFFF;
        ly [i] = 0;
        for (j = 0; j < n; j ++)
            if (lx [i] < weight [i] [j])
                lx [i] = weight [i] [j];
	}

    memset (match, -1, sizeof (match));
    for (int u = 0; u < n; u ++)
        while (1) {
            memset (sx, 0, sizeof (sx));
            memset (sy, 0, sizeof (sy));
            if (path (u))
                break;

            // 修改标号
            int dx = 0x7FFFFFFF;
            for (i = 0; i < n; i ++)
                if (sx [i])
                    for (j = 0; j < n; j ++)
                        if(!sy [j])
                            dx = min (lx[i] + ly [j] - weight [i] [j], dx);
            for (i = 0; i < n; i ++) {
                if (sx [i])
                    lx [i] -= dx;
                if (sy [i])
                    ly [i] += dx;
			}
		}

    int sum = 0;
    for (i = 0; i < n; i ++)
        sum += weight [match [i]] [i];

    if (!maxsum) {
        sum = -sum;
        for (i = 0; i < n; i ++)
            for (j = 0; j < n; j ++)
                weight [i] [j] = -weight [i] [j];         // 还原weight [ ] [ ]的值
	}
    return sum;
}
int main()
{
    int n,i;
    scanf ("%d", &n);
    init (n);
    int cost = bestmatch (true);

    printf ("%d ", cost);
    for (i = 0; i < n; i++) {
        printf ("Y %d -> X %d ", i, match [i]);
	}
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值