zoukankan      html  css  js  c++  java
  • Codeforces 844F Anti-Palindromize 最小费用流

    Anti-Palindromize

    想到网络流就差不多了, 拆拆点, 建建边。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ull unsigned long long
    
    using namespace std;
    
    const int N = 1500 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-9;
    const double PI = acos(-1);
    
    int edgenum, S, T;
    int head[N], dist[N], pre[N];
    bool vis[N];
    
    struct Edge {
        int from, to, cap, flow, cost, next;
    } edge[1000007];
    
    void MCMFinit() {
        edgenum = 0;
        memset(head, -1, sizeof(head));
    }
    
    void addEdge(int u, int v, int w, int c) {
        Edge E1 = {u, v, w, 0, c, head[u]};
        edge[edgenum] = E1;
        head[u] = edgenum++;
        Edge E2 = {v, u, 0, 0, -c, head[v]};
        edge[edgenum] = E2;
        head[v] = edgenum++;
    }
    
    bool SPFA(int s, int t) {
        queue<int> Q;
        memset(dist, INF, sizeof(dist));
        memset(vis, false, sizeof(vis));
        memset(pre, -1, sizeof(pre));
        dist[s] = 0; vis[s] = true; Q.push(s);
        while(!Q.empty()) {
            int u = Q.front(); Q.pop(); vis[u] = false;
            for(int i = head[u]; i != -1; i = edge[i].next) {
                Edge E = edge[i];
                if(dist[E.to] > dist[u] + E.cost && E.cap > E.flow) {
                    dist[E.to] = dist[u] + E.cost;
                    pre[E.to] = i;
                    if(!vis[E.to]) {
                        vis[E.to] = true;
                        Q.push(E.to);
                    }
                }
            }
        }
        return pre[t] != -1;
    }
    
    void MCMF(int s, int t, int &cost, int &flow) {
        flow = 0; cost = 0;
        while(SPFA(s, t)) {
            int Min = INF;
            for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) {
                Edge E = edge[i];
                Min = min(Min, E.cap - E.flow);
            }
            for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) {
                edge[i].flow += Min;
                edge[i^1].flow -= Min;
                cost += edge[i].cost * Min;
            }
            flow += Min;
        }
    }
    
    int n;
    char s[N];
    int a[N], b[N];
    int cnt[100];
    
    int main() {
        MCMFinit();
        scanf("%d", &n);
        S = 0, T = (n / 2 + 1) * 26 + n + 1;
        int B = (n / 2 + 1);
        int G = (n / 2 + 1) * 26;
        scanf("%s", s + 1);
        for(int i = 1; i <= n; i++) scanf("%d", &b[i]);
        for(int i = 1; i <= n; i++) {
            a[i] = s[i] - 'a' + 1;
            cnt[a[i]]++;
        }
        for(int i = 1, o = 1; i <= G; i += B, o++) {
            addEdge(S, i, cnt[o], 0);
            for(int j = 1; j < B; j++) {
                addEdge(i, i + j, 1, 0);
                int c1 = a[j] == o ? -b[j] : 0;
                int c2 = a[n - j + 1] == o ? -b[n - j + 1] : 0;
                addEdge(i + j, G + j, 1, c1);
                addEdge(i + j, G + n - j + 1, 1, c2);
            }
        }
        for(int i = 1; i <= n; i++) addEdge(G + i, T, 1, 0);
        int cost = 0, flow = 0;
        MCMF(S, T, cost, flow);
        printf("%d
    ", -cost);
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    CF 436D 最小生成树
    HDU 1847 博弈
    ZOJ 3666 博弈 SG函数
    zoj3675 BFS+状态压缩
    HDU 4734 F(x) 数位DP
    HDU 3709 Balanced Number 数位DP
    HDU 3555 数位DP
    HDU 4336 Card Collector
    HDU4340 Capturing a country DP
    CF 351A
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10663378.html
Copyright © 2011-2022 走看看