zoukankan      html  css  js  c++  java
  • Codeforces 237E (最小费用最大流)

      很明显的费用流,不过建图还是卡住了。。。问的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;
    }
  • 相关阅读:
    是否需要self.loss.cuda()
    多loss的反向传播路径
    RuntimeError: Function 'AddmmBackward' returned nan values in its 2th output.
    【转载】Linux下configure命令详细介绍
    【转载】移植FFMpeg到VC环境心得
    【转载】WIN7环境下Virtualbox虚拟机Ubuntu系统共享文件夹设置
    【转载】在Ubuntu中使用Android NDK编译FFmpeg
    CYGWIN下编译FFMpeg
    Linux操作系统安装应用程序
    CapsNet胶囊网络(理解)
  • 原文地址:https://www.cnblogs.com/vongang/p/2742083.html
Copyright © 2011-2022 走看看