zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    H5软键盘搜索
    ios顺畅滑动
    自定义滚动条样式
    mockjs模拟数据(本地版)
    移动端防止窗体滚动
    css超出部分省略号
    H5自带的type=date或者month等日期控件移动端显示placeholder
    判断是否在微信内打开
    滚动加载数据
    activemq 5.6 连接池的内存泄露问题
  • 原文地址:https://www.cnblogs.com/1-1-1-1/p/8038079.html
Copyright © 2011-2022 走看看