zoukankan      html  css  js  c++  java
  • BZOJ 2127: happiness( 最小割 )

     最小割..

    S连每个人(容量:选择理科的愉悦);每个人连T(容量:选择理科的愉悦) .

    对于每一组(x, y, w)x和y同选理增加的愉悦w,新建节点V,V连x(INF),V连y(INF), S连V(w)

    对于每一组(x, y, w)x和y同选文增加的愉悦w,新建节点V,x连V(INF),y连V(INF), V连T(w)

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

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
     
    using namespace std;
     
    const int maxn = 60000;
    const int INF = 100000000;
     
    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;
    }
     
    int N, M, S, T, V, tot = 0;
     
    struct edge {
    int to, cap;
    edge *next, *rev;
    } E[10000000], *pt = E, *head[maxn];
     
    void Add(int u, int v, int w) {
    pt->to = v; pt->cap = w; pt->next = head[u]; head[u] = pt++;
    }
    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];
    }
     
    edge *p[maxn], *cur[maxn];
    int h[maxn], cnt[maxn];
     
    int maxFlow() {
    memset(cnt, 0, sizeof cnt);
    memset(h, 0, sizeof h);
    for(int i = 0; i < V; i++)
    cur[i] = head[i];
    cnt[0] = V;
    int Flow = 0;
    edge* e;
    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) {
    p[e->to] = cur[x] = e;
    A = min(A, e->cap);
    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(h[e->to] + 1 < h[x] && e->cap) {
    h[x] = h[e->to] + 1;
    cur[x] = e;
    }
    cnt[h[x]]++;
    if(x != S)
    x = p[x]->rev->to;
    }
    }
    return Flow;
    }
     
    void Init() {
    scanf("%d%d", &N, &M);
    S = N * M; T = S + 1;
    for(int i = 0; i < N; i++)
    for(int j = 0; j < M; j++) {
    int v = read();
    tot += v;
    AddEdge(i * M + j, T, v);
    }
    for(int i = 0; i < N; i++)
    for(int j = 0; j < M; j++) {
    int v = read();
    tot += v;
    AddEdge(S, i * M + j, v);
    }
    V = T;
    for(int i = 1; i < N; i++)
    for(int j = 0; j < M; j++) {
    int v = read();
    tot += v;
    AddEdge(++V, T, v);
    AddEdge(i * M + j, V, INF);
    AddEdge((i - 1) * M + j, V, INF);
    }
    for(int i = 1; i < N; i++)
    for(int j = 0; j < M; j++) {
    int v = read();
    tot += v;
    AddEdge(S, ++V, v);
    AddEdge(V, i * M + j, INF);
    AddEdge(V, (i - 1) * M + j, INF);
    }
    for(int i = 0; i < N; i++)
    for(int j = 1; j < M; j++) {
    int v = read();
    tot += v;
    AddEdge(++V, T, v);
    AddEdge(i * M + j, V, INF);
    AddEdge(i * M + j - 1, V, INF);
    }
    for(int i = 0; i < N; i++)
    for(int j = 1; j < M; j++) {
    int v = read();
    tot += v;
    AddEdge(S, ++V, v);
    AddEdge(V, i * M + j, INF);
    AddEdge(V, i * M + j - 1, INF);
    }
    ++V;
    }
     
    int main() {
    Init();
    printf("%d ", tot - maxFlow());
    return 0;
    }

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

    2127: happiness

    Time Limit: 51 Sec  Memory Limit: 259 MB
    Submit: 1119  Solved: 530
    [Submit][Status][Discuss]

    Description

    高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值。作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大。

    Input

    第一行两个正整数n,m。接下来是六个矩阵第一个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择文科获得的喜悦值。第二个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择理科获得的喜悦值。第三个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择文科获得的额外喜悦值。第四个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择理科获得的额外喜悦值。第五个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择文科获得的额外喜悦值。第六个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择理科获得的额外喜悦值。

    Output

    输出一个整数,表示喜悦值总和的最大值

    Sample Input

    1 2
    1 1
    100 110
    1
    1000

    Sample Output

    1210
    【样例说明】
    两人都选理,则获得100+110+1000的喜悦值。
    【数据规模】
    对于100%以内的数据,n,m<=100 所有喜悦值均为小于等于5000的非负整数

    HINT

    Source

  • 相关阅读:
    python 学习笔记(四)(流程控制)
    python 写斐波那契数列
    python 部分术语对照表
    python 学习笔记(三)(对前两节的补充)
    python # -*- coding: utf-8 -*-
    写出更好的 JavaScript 条件语句
    PHP消息队列实现及应用
    VUE3.0 路由去掉#号
    php设计模式
    workerman 可能需要用到的函数
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4995857.html
Copyright © 2011-2022 走看看