zoukankan      html  css  js  c++  java
  • P2805 [NOI2009]植物大战僵尸(最小割+拓扑排序)

    题意:

      n*m的矩阵,每个位置都有一个植物。每个植物都有一个价值(可以为负),以及一些它可以攻击的位置。从每行的最右面开始放置僵尸,僵尸从右往左行动,当僵尸在植物攻击范围内时会立刻死亡。僵尸每到一个位置可以获得该位置植物的价值。僵尸可以无限放置,求最大的价值和。

    题解:

      这种模型好像叫做最大权闭合子图。

      首先通过拓扑排序将成环的点(即植物互相保护无法走到的点)删掉。

      之后对于剩下的点A,若w > 0,则S→A连权值为w的边。

      若w < 0,则A→T连权值为-w的边。

      若A保护B(即B在A攻击范围内),则B→A连权值为INF的边。

      注意每个点也被它右面的点保护。

      最后跑一边最小割,答案为:正的价值和(即w > 0的和) - 最小割。

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 605;
    const int INF = 2e9;
    int n, m;
    int level[N];
    int iter[N];
    int x, y;
    int w[N], d[N];
    vector<int> g[N];
    vector<int> a;
    struct edge {
        int to, cap, rev;
    };
    vector<edge> G[N];
    void add_edge(int from, int to, int cap) {
        G[from].push_back((edge){to, cap, G[to].size()});
        G[to].push_back((edge){from, 0, G[from].size()-1});
    }
    void bfs(int s) {
        memset(level, -1, sizeof(level));
        queue<int> que;
        level[s] = 0;
        que.push(s);
        while(!que.empty()) {
            int v = que.front(); que.pop();
            int len = G[v].size();
            for(int i = 0; i < len; i++) {
                edge &e = G[v][i];
                if(e.cap > 0 && level[e.to] < 0) {
                    level[e.to] = level[v]+1;
                    que.push(e.to);
                }
            }
        }
    } 
    int dfs(int v, int t, int f) {
        if(v == t) return f;
        int len = G[v].size(); 
        for(int &i = iter[v]; i < len; i++) {
            edge &e = G[v][i];
            if(e.cap > 0 && level[v] < level[e.to]) {
                int d = dfs(e.to, t, min(f, e.cap));
                if(d > 0) {
                    e.cap -= d;
                    G[e.to][e.rev].cap += d;
                    return d;
                }
            }
        }
        return 0;
    } 
    int max_flow(int s, int t) {
        int flow = 0;
        for(;;) {
            bfs(s);
            if(level[t] < 0) return flow;
            memset(iter, 0, sizeof(iter));
            int f;
            while((f = dfs(s, t, INF)) > 0) flow += f;
        }
    } 
    int main() {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n*m; i++) {
            int num;
            scanf("%d%d", &w[i], &num);
            while(num--) {
                scanf("%d%d", &x, &y);
                int id = x*m+y+1;
                g[i].push_back(id);
                d[id]++;
            }
            if(i % m != 1) g[i].push_back(i-1), d[i-1]++;
        }
        queue<int> q;
        for(int i = 1; i <= n*m; i++) if(!d[i]) q.push(i);
        while(!q.empty()) {
            int v = q.front(); q.pop();
            a.push_back(v);
            int len = g[v].size();
            for(int i = 0; i < len; i++) {
                int to = g[v][i];
                d[to]--;
                if(!d[to]) q.push(to);
            }
        }
        int sum = 0;
        int len = a.size();
        for(int i = 0; i < len; i++) {
            int v = a[i];
            if(w[v] >= 0) {
                sum += w[v];
                add_edge(0, v, w[v]);
            }
            else add_edge(v, n*m+1, -w[v]);
            int up = g[v].size();
            for(int j = 0; j < up; j++) add_edge(g[v][j], v, INF);
        }
        printf("%d
    ", sum-max_flow(0, n*m+1));
    }
    View Code
  • 相关阅读:
    leetcode 77 组合
    leetcode 40组合总和 II
    leetcode 216 组合总和III
    弹性伸缩 AS(Auto Scaling)
    弹性计算服务(Elastic Compute Service) / 云服务器 ECS
    云计算概述
    Zabbix Proxy 分布式监控
    Zabbix 自动发现 & 自动注册
    LVS-DR 模式
    GoAccess 监控工具
  • 原文地址:https://www.cnblogs.com/Pneuis/p/9858758.html
Copyright © 2011-2022 走看看