zoukankan      html  css  js  c++  java
  • BZOJ 1565: [NOI2009]植物大战僵尸( 最小割 )

     

    先拓扑排序搞出合法的, 然后就是最大权闭合图模型了.... 

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

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
     
    using namespace std;
     
    #define Id(x, y) ((x) * c + (y))
     
    const int maxv = 700;
    const int INF = 10000000;
     
    int r, c;
    int deg[maxv], w[maxv], q[maxv], Id[maxv];
     
    struct edge {
    int t;
    edge* nxt;
    } E[maxv * maxv], *pt = E, *Head[maxv];
     
    inline void AddEdge(int u, int v) {
    deg[pt->t = v]++, pt->nxt = Head[u], Head[u] = pt++;
    }
     
    namespace G {
    struct edge {
    int t, c;
    edge *nxt, *rev;
    } E[maxv * maxv], *e = E, *Head[maxv], *p[maxv], *cur[maxv];
    int V, h[maxv], cnt[maxv];
    inline void Add(int u, int v, int c) {
    e->t = v, e->c = c, e->nxt = Head[u], Head[u] = e++;
    }
    inline void AddEdge(int u, int v, int c) {
    Add(u, v, c), Add(v, u, 0);
    Head[u]->rev = Head[v];
    Head[v]->rev = Head[u];
    }
    void Work() {
    int S = V++, T = V++, ans = 0;
    for(int i = r * c; i--; ) if(~Id[i]) {
    if(w[i] > 0) {
    ans += w[i], AddEdge(S, Id[i], w[i]);
    } else
    AddEdge(Id[i], T, -w[i]);
    }
    for(int i = 0; i < V; i++)
    cnt[i] = h[i] = 0, cur[i] = Head[i];
    cnt[0] = V;
    for(int x = S, A = INF; h[S] < V; ) {
    for(e = cur[x]; e; e = e->nxt)
    if(e->c && h[e->t] + 1 == h[x]) break;
    if(e) {
    p[e->t] = cur[x] = e;
    A = min(A, e->c);
    if((x = e->t) == T) {
    for(; x != S; x = p[x]->rev->t)
    p[x]->c -= A, p[x]->rev->c += A;
    ans -= A, A = INF;
    }
    } else {
    if(!--cnt[h[x]]) break;
    h[x] = V;
    for(e = Head[x]; e; e = e->nxt) if(h[e->t] + 1 < h[x] && e->c)
    h[x] = h[e->t] + 1, cur[x] = e;
    cnt[h[x]]++;
    if(x != S) x = p[x]->rev->t;
    }
    }
    printf("%d ", ans);
    }
    }
     
    void Init() {
    int n;
    scanf("%d%d", &r, &c);
    memset(deg, 0, sizeof deg);
    memset(Id, -1, sizeof Id);
    for(int i = 0; i < r; i++)
    for(int j = 0; j < c; j++) {
    scanf("%d%d", w + Id(i, j), &n);
    while(n--) {
    int x, y; scanf("%d%d", &x, &y);
    AddEdge(Id(i, j), Id(x, y));
    }
    if(j) AddEdge(Id(i, j), Id(i, j - 1));
    }
    }
     
    void BFS() {
    int h = 0, t = 0, x, &V = G::V = 0;
    for(int i = r * c; i--; )
    if(!deg[i]) q[t++] = i;
    while(h < t) {
    Id[x = q[h++]] = V++;
    for(edge* e = Head[x]; e; e = e->nxt)
    if(!--deg[e->t]) q[t++] = e->t;
    }
    }
     
    void Work() {
    for(int i = r * c; i--; ) if(~Id[i])
    for(edge* e = Head[i]; e; e = e->nxt)
    if(~Id[e->t]) G::AddEdge(Id[e->t], Id[i], INF);
    G::Work();
    }
     
    int main() {
    Init();
    BFS();
    Work();
    return 0;
    }

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

    1565: [NOI2009]植物大战僵尸

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 1807  Solved: 835
    [Submit][Status][Discuss]

    Description

    Input

    Output

    仅包含一个整数,表示可以获得的最大能源收入。注意,你也可以选择不进行任何攻击,这样能源收入为0。

    Sample Input

    3 2
    10 0
    20 0
    -10 0
    -5 1 0 0
    100 1 2 1
    100 0

    Sample Output

    25

    HINT

    在样例中, 植物P1,1可以攻击位置(0,0), P2, 0可以攻击位置(2,1)。 
    一个方案为,首先进攻P1,1, P0,1,此时可以攻击P0,0 。共得到能源收益为(-5)+20+10 = 25。注意, 位置(2,1)被植物P2,0保护,所以无法攻击第2行中的任何植物。 
    【大致数据规模】
    约20%的数据满足1 ≤ N, M ≤ 5;
    约40%的数据满足1 ≤ N, M ≤ 10;
    约100%的数据满足1 ≤ N ≤ 20,1 ≤ M ≤ 30,-10000 ≤ Score ≤ 10000 。

    Source

  • 相关阅读:
    实现一个简易的Spring MVC
    解决IntelIij DEA控制台乱码
    01、SpringBoot中关于tomcat的一些常用配置
    Java动态代理的简单实现
    MVVM中viewmodel的理解
    eclipse常用快捷键
    导入mysql报错问题
    mysql主从配置思路
    rpm安装jdk7
    13个开源GIS软件 你了解几个?
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/5154311.html
Copyright © 2011-2022 走看看