BZOJ1565 植物大战僵尸 题解

题目内容:

题目分析:有选A则必须选B这样的限制条件,可以发现这是最大权闭合子图模型,考虑环的情况,可以推测需要拓扑判环。

代码:

#include<bits/stdc++.h>
using namespace std;

struct edge{
    int from,to,flow;
}e[520000];

const int maxn = 35,inf = 1000000000;
int n,m,num,tmp = 1500;
int sc[maxn][maxn];
vector <int> at[maxn][maxn];
vector <int> g[maxn*maxn+1000];
vector <int> ng[maxn*maxn+1000];

void AddEdge(int from,int to,int w){
    e[num++] = (edge){from,to,w}; g[from].push_back(num-1);
    e[num++] = (edge){to,from,0}; g[to].push_back(num-1);
}

int tp[maxn*maxn+1000],in[maxn*maxn+1000];
void topu(){
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
        if(j < m)ng[(i-1)*m+j+1].push_back((i-1)*m+j),in[(i-1)*m+j]++;
        for(int k=0;k<at[i][j].size();k++){
        int now = at[i][j][k];
        ng[(i-1)*m+j].push_back(now);
        in[now] ++;
        }
    }
    queue <int> q;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)if(!in[(i-1)*m+j])q.push((i-1)*m+j);
    while(!q.empty()){
    int k = q.front();q.pop();
    tp[k] = 1;
    for(int i=0;i<ng[k].size();i++){
        in[ng[k][i]]--;
        if(!in[ng[k][i]])q.push(ng[k][i]);
    }
    }
    for(int i=1;i<=n*m;i++)ng[i].clear();
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
        if(j < m)ng[(i-1)*m+j+1].push_back((i-1)*m+j);
        for(int k=0;k<at[i][j].size();k++){
        int now = at[i][j][k],now2 = (i-1)*m+j;
        ng[now2].push_back(now);
        }
    }
    for(int i=1;i<=n*m;i++) if(tp[i] == 0) q.push(i);
    while(!q.empty()){
    int k = q.front();q.pop();
    for(int i=0;i<ng[k].size();i++){
        if(tp[ng[k][i]]==0)continue;
        tp[ng[k][i]]=0;q.push(ng[k][i]);
    }
    }
}

void build_graph(){
    topu();
    for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++){
        if(tp[(i-1)*m+j]==0)continue;
        if(sc[i][j] > 0)AddEdge(0,(i-1)*m+j,sc[i][j]);
        else AddEdge((i-1)*m+j,tmp,-sc[i][j]);
        for(int k=0;k<at[i][j].size();k++){
        int now = at[i][j][k];
        if(tp[now]==0)continue;
        AddEdge(now,(i-1)*m+j,inf);
        }
        if(j < m && tp[(i-1)*m+j+1])AddEdge((i-1)*m+j,(i-1)*m+j+1,inf);
    }
    }
}

void read(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
    for(int j=1,x;j<=m;j++){
        scanf("%d%d",&sc[i][j],&x);
        for(int k=1,p1,q1;k<=x;k++) {
        scanf("%d%d",&p1,&q1);p1++;q1++;
        at[i][j].push_back((p1-1)*m+q1);
        }
    }
    }
    build_graph();
}

int dis[maxn*maxn+1000],cur[maxn*maxn+1000];
int BFS(){
    queue <int> q;
    memset(dis,-1,sizeof(dis));
    q.push(0); dis[0] = 0;
    while(!q.empty()){
    int k = q.front();q.pop();
    for(int i=0;i<g[k].size();i++){
        edge nxt = e[g[k][i]];
        if(nxt.flow > 0 && (dis[nxt.to]==-1)){
        dis[nxt.to] = dis[k]+1; q.push(nxt.to);
        }
    }
    }
    return dis[tmp];
}

int dfs(int x,int a){
    if(x == tmp || a == 0) return a;
    int flow = 0,f;
    for(int &i=cur[x];i<g[x].size();i++){
    edge &eg = e[g[x][i]];
    if(dis[eg.to] > dis[x] && ((f = dfs(eg.to,min(eg.flow,a)))>0)){
        eg.flow -= f;
        e[g[x][i]^1].flow += f;
        a -= f; flow += f;
        if(a == 0) break;
    }
    }
    return flow;
}

void work(){
    int flow;
    while(BFS()!=-1){
    memset(cur,0,sizeof(cur));
    flow = dfs(0,inf);
    }
    int ans = 0;
    for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++){
        if(dis[(i-1)*m+j]!=-1) ans += sc[i][j];
    }
    }
    printf("%d",ans);
}

int main(){
    read();
    work();
    return 0;
}
原文地址:https://www.cnblogs.com/1-1-1-1/p/8038079.html