• BZOJ 1412: [ZJOI2009]狼和羊的故事( 最小割 )


    显然是最小割...把狼的领地连S, 羊的领地连T, 然后中间再连边, 跑最大流就OK了 

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

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
     
    using namespace std;
     
    const int maxn = 10009;
    const int INF = 100000000;
     
    struct edge {
    int to, cap;
    edge *next, *rev;
    } E[100000], *pt = E, *head[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];
    }
     
    edge *p[maxn], *cur[maxn];
    int cnt[maxn], h[maxn], mp[109][109], S, T, N;
     
    int maxFlow() {
    for(int i = 0; i < N; i++) cur[i] = head[i];
    memset(cnt, 0, sizeof cnt); cnt[0] = N;
    memset(h, 0, sizeof h);
    int flow = 0;
    edge* e;
    for(int A = INF, x = S; h[S] < N; ) {
    for(e = cur[x]; e; e = e->next)
       if(h[e->to] + 1 == h[x] && e->cap) break;
    if(e) {
    p[e->to] = cur[x] = e;
    A = min(A, e->cap);
    x = e->to;
    if(x == T) {
    flow += A;
    for(; x != S; x = p[x]->rev->to) {
    p[x]->cap -= A;
    p[x]->rev->cap += A;
    }
    A = INF;
    }
    } else {
    if(!--cnt[h[x]]) break;
    h[x] = N;
    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;
    }
    }
    return flow;
    }
     
    #define id(i, j) ((i) * m + (j))
    void init() {
    int n, m; scanf("%d%d", &n, &m);
    S = n * m; T = S + 1; N = T + 1;
    for(int i = 0; i < n; i++)
       for(int j = 0; j < m; j++)
           scanf("%d", mp[i] + j);
    for(int i = 0; i < n; i++) 
       for(int j = 0; j < m; j++) {
        if(mp[i][j] == 1) addedge(S, id(i, j), INF);
        if(mp[i][j] == 2) addedge(id(i, j), T, INF);
        if(i - 1 >= 0 && (mp[i][j] != mp[i - 1][j] || !(mp[i][j] | mp[i - 1][j])))
        addedge(id(i, j), id(i - 1, j), 1);
        if(i + 1 < n && (mp[i][j] != mp[i + 1][j] || !(mp[i][j] | mp[i + 1][j])))
        addedge(id(i, j), id(i + 1, j), 1);
        if(j - 1 >= 0 && (mp[i][j] != mp[i][j - 1] || !(mp[i][j] | mp[i][j - 1])))
        addedge(id(i, j), id(i, j - 1), 1);
        if(j + 1 < m && ((mp[i][j] != mp[i][j + 1]) || !(mp[i][j] | mp[i][j+ 1])))
        addedge(id(i, j), id(i, j + 1), 1);
       }
    }
     
    int main() {
    init();
    printf("%d ", maxFlow());
    return 0;
    }

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

    1412: [ZJOI2009]狼和羊的故事

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1851  Solved: 961
    [Submit][Status][Discuss]

    Description

    “狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。 Orez想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。

    Input

    文件的第一行包含两个整数n和m。接下来n行每行m个整数,1表示该格子属于狼的领地,2表示属于羊的领地,0表示该格子不是任何一只动物的领地。

    Output

    文件中仅包含一个整数ans,代表篱笆的最短长度。

    Sample Input

    2 2
    2 2
    1 1

    Sample Output

    2

    数据范围
    10%的数据 n,m≤3
    30%的数据 n,m≤20
    100%的数据 n,m≤100

    HINT

    Source

  • 相关阅读:
    <剑指OFFER18> 18_01_DeleteNodeInList在O(1)时间删除链表结点
    哈夫曼树

    快速排序
    冒泡算法
    Java 缓存机制
    JAVA NIO
    string、stringbuilder、stringbuffer区别
    Java内存泄露的问题调查定位
    使用hibernate 框架搭建的helloworld
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4811641.html
Copyright © 2020-2023  润新知