现在的位置: 首页 > 综合 > 正文

Codeforces 237E (最小费用最大流)

2012年11月17日 ⁄ 综合 ⁄ 共 2819字 ⁄ 字号 评论关闭

  很明显的费用流,不过建图还是卡住了。。。问的gb才知道怎么建图。。。

先是源点到n个串,容量是a[i],费用是0,然后是串t中包含的所有不重复字母为一个节点,从这些节点向汇点T连边,容量是当前字母的个数,费用是0。

然后是n个串向T中的字母连边,容量是a[i]中当前字母的个数,费用是i。

 

ps:费用流模板有问题。以至于debug了好久。。。T_T

 

View Code

//#pragma comment(linker,"/STACK:327680000,327680000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("data.in", "r", stdin)
#define Write() freopen("data.out", "w", stdout);

const double eps = 1e-8;
typedef long long LL;
const int inf = ~0u>>2;

using namespace std;

const int N = 1024;



struct node {
    int from, to, cost, flow, next;   //
} g[N*N];

int S, T;
int head[N], t;

void init() {
    CL(head, -1); t = 0;
}

void add(int u, int v, int f, int w) {
    g[t].from = u; g[t].to = v; g[t].flow = f; g[t].cost = w;
    g[t].next = head[u]; head[u] = t++;

    g[t].from = v; g[t].to = u; g[t].flow = 0; g[t].cost = -w;
    g[t].next = head[v]; head[v] = t++;
}


int dis[N];
int pre[N];
bool vis[N];
queue<int> q;

bool spfa() {    //找最大费用
    while(!q.empty())   q.pop();

    for(int i = 0; i < N; ++i) {
        dis[i] = inf; pre[i] = -1; vis[i] = false;
    }

    q.push(S); dis[S] = 0;
    vis[S] = true; pre[S] = -1;

    int u, v, w, i;
    while(!q.empty()) {
        u = q.front(); q.pop();
        for(i = head[u]; i != -1; i = g[i].next) {
            v = g[i].to;
            w = g[i].cost;
            if(g[i].flow && dis[v] > dis[u] + w) {
                dis[v] = dis[u] + w;
                pre[v] = i;
                if(!vis[v]) {
                    vis[v] = true; q.push(v);
                }
            }
        }
        vis[u] = false;
    }
    return dis[T] != inf;
}

int get_flow(int& Cost, int& Flow) {    //增广路
    int tmp = T;
    int res = inf;
    int c = 0;

    while(pre[tmp] != -1) {
        res = min(res, g[pre[tmp]].flow);
        tmp = g[pre[tmp]].from;
    }
    tmp = T;
    while(pre[tmp] != -1) {
        g[pre[tmp]].flow -= res;
        g[pre[tmp]^1].flow += res;
        c += g[pre[tmp]].cost*res;
        tmp = g[pre[tmp]].from;
    }
    //printf("%d %d\n", c, res);
    Cost += c; Flow += res;
}


char sst[N];
char dic[N][N];
int hh[50], ht[50];
int a[N], n, lent;

int solve() {
    int Cost = 0, Flow = 0;    //...
    while(spfa()) {
        get_flow(Cost, Flow);
    }
    //printf("%d %d\n", Flow, Cost);
    if(Flow == lent)    return Cost;
    else    return -1;
}



void build() {
    init();
    S = 0; T = 127;
    lent = strlen(sst);
    int i, j;
    CL(hh, 0);

    for(i = 0; i < lent; ++i) {
        hh[sst[i]-'a' + 1]++;
    }
    for(i = 1; i <= 26; ++i) {
        if(hh[i]) {
            add(100 + i, T, hh[i], 0);
            //printf("%d -> %d %d %d\n", 100 + i, T, hh[i], 0);
        }
    }
    for(i = 1; i <= n; ++i) {
        add(S, i, a[i], 0);
        //printf("%d -> %d %d %d\n", S, i, a[i], 0);
    }
    for(i = 1; i <= n; ++i) {
        CL(ht, 0);
        for(j = 0; j < static_cast<int>(strlen(dic[i])); ++j) {
            ht[dic[i][j] - 'a' + 1] ++;
        }
        for(j = 1; j <= 26; ++j) {
            if(ht[j] && hh[j]) {
                add(i, 100 + j, ht[j], i);
                //printf("%d -> %d %d %d\n", i, 100 + j, ht[j], i);
            }
        }
    }
}


int main() {
    //Read();

    scanf("%s", sst);
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        scanf("%s %d", dic[i], &a[i]);
    }
    build();
    printf("%d\n", solve());
    return 0;
}

抱歉!评论已关闭.