zoukankan      html  css  js  c++  java
  • BZOJ 3774: 最优选择( 最小割 )

    最小割...二分染色然后把颜色不同的点的源汇反过来..然后就可以做了.

    某个点(x,y):

    S->Id(x,y)(回报), Id(x,y)->T(代价), Id(i,j)&&Id(相邻节点)->newId(i,j)(+oo), newId(i,j)->T(回报)

    然后染色不同的点反过来就可以了.

    初始时答案为2*∑回报, 这样每个点要么割掉1个回报,要么割掉2个回报, 要么割掉1回报+代价.都对应着每一种方案

    --------------------------------------------------------------------------------

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
     
    using namespace std;
     
    #define Id(x, y) ((x) * M + (y))
    #define chk(x, y) (0 <= (x) && (x) < N && 0 <= (y) && (y) < M)
     
    const int maxn = 5009;
    const int INF = 1 << 30;
    const int dx[4] = {-1, 0, 0, 1};
    const int dy[4] = {0, 1, -1, 0};
     
    inline int read() {
    char c = getchar();
    int ret = 0;
    for(; !isdigit(c); c = getchar());
    for(; isdigit(c); c = getchar()) ret = ret * 10 + c - '0';
    return ret;
    }
     
    struct edge {
    int to, cap;
    edge *next, *rev;
    } E[5000000], *pt = E, *head[maxn], *p[maxn], *cur[maxn];
     
    inline void Add(int u, int v, int w) {
    pt->to = v;
    pt->cap = w;
    pt->next = head[u];
    head[u] = pt++;
    }
    inline void AddEdge(int u, int v, int w) {
    Add(u, v, w);
    Add(v, u, 0);
    head[u]->rev = head[v];
    head[v]->rev = head[u];
    }
     
    int N, M, S, T, V, ans;
    int h[maxn], cnt[maxn];
     
    void Solve() {
    for(int i = 0; i < V; i++) cur[i] = head[i];
    memset(cnt, 0, sizeof cnt);
    memset(h, 0, sizeof h);
    cnt[0] = V;
    edge* e;
    int Flow = 0;
    for(int x = S, A = INF; h[S] < V; ) {
    for(e = cur[x]; e; e = e->next)
    if(e->cap && h[e->to] + 1 == h[x]) break;
    if(e) {
    A = min(A, e->cap);
    cur[x] = p[e->to] = e;
    if((x = e->to) == T) {
    for(; x != S; x = p[x]->rev->to) {
    p[x]->cap -= A;
    p[x]->rev->cap += A;
    }
    Flow += A;
    A = INF;
    }
    } else {
    if(!--cnt[h[x]]) break;
    h[x] = V;
    for(e = head[x]; e; e = e->next) if(e->cap && h[e->to] + 1 < h[x]) {
    h[x] = h[e->to] + 1;
    cur[x] = e;
    }
    cnt[h[x]]++;
    if(x != S)
    x = p[x]->rev->to;
    }
    }
    printf("%d ", (ans << 1) - Flow);
    }
     
    void Init() {
    N = read(); M = read();
    V = N * M; S = V++; T = V++;
    for(int i = 0; i < N; i++)
    for(int j = 0; j < M; j++)
    (i + j) & 1 ? AddEdge(Id(i, j), T, read()) : AddEdge(S, Id(i, j), read());
    ans = 0;
    for(int i = 0; i < N; i++)
    for(int j = 0; j < M; j++) {
    int v = read(), np = V++;
    ans += v;
    if((i + j) & 1) {
    AddEdge(S, Id(i, j), v);
    AddEdge(np, T, v);
    AddEdge(Id(i, j), np, INF);
    for(int k = 0; k < 4; k++) {
    int x = i + dx[k], y = j + dy[k];
    if(chk(x, y))
    AddEdge(Id(x, y), np, INF);
    }
    } else {
    AddEdge(Id(i, j), T, v);
    AddEdge(S, np, v);
    AddEdge(np, Id(i, j), INF);
    for(int k = 0; k < 4; k++) {
    int x = i + dx[k], y = j + dy[k];
    if(chk(x, y))
    AddEdge(np, Id(x, y), INF);
    }
    }
    }
    }
     
    int main() {
    Init();
    Solve();
    return 0;
    }

    -------------------------------------------------------------------------------- 

    3774: 最优选择

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 96  Solved: 48
    [Submit][Status][Discuss]

    Description

    小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择了的。一个点如果被选择了,那么可以得到Bij的回报,现在请你帮小N选一个最优的方案,使得回报-代价尽可能大。

    Input

    第一行两个正整数N,M表示方格图的长与宽。

    接下来N行每行M个整数Aij表示控制的代价。

    接下来N行每行M个整数Bij表示选择的回报。

    Output

    一个整数,表示最大的回报-代价(如果一个都不控制那么就是0)。

    Sample Input

    3 3
    1 100 100
    100 1 100
    1 100 100
    2 0 0
    5 2 0
    2 0 0

    Sample Output

    8

    HINT

    对于100%的数据,N,M<=50Aij,Bij都是小于等于100的正整数。


    Source

  • 相关阅读:
    KVM学习(初步安装与使用)
    读书笔记之Linux系统编程与深入理解Linux内核
    深入理解linux关闭文件和删除文件
    读书笔记之大型网站架构:核心原理与架构分析
    读书笔记之深入理解Nginx:模块开发与结构解析
    python socket server源码学习
    python文本处理--定位motif在fasta文件上的位置,并给出位置信息
    python文本处理练习-4
    python文件处理,去除内含子,拼接外显子
    python处理fasta文件,ID和序列放在一行
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/5067988.html
Copyright © 2011-2022 走看看