zoukankan      html  css  js  c++  java
  • 【bzoj1565】[NOI2009]植物大战僵尸 【网络流】【最大权闭合子图】

    题解:可以看出每个格子有一些前驱,只有前驱都被消灭了才能走到这里。因为要求最大的权值和,所以我们可以用最大权闭合子图来求解这题。最大权闭合子图点这里!
    然后让蒟蒻讲一讲自己掉的坑。
    首先,根据WYC大佬的博客,我们要先进行一次拓扑排序来把因出现了环而无敌的格子排除出去。
    然后我就掉了一个坑拓扑排序建边应该是与网络流建边反向的,因为按照最大权闭合子图的建法,环上连出去的边连到的是保护环上格子的,这些格子是可以被收集的,但是如果按照这种建法,拓扑排序时永远都不会拓展到这些格子。所以要反向建边。
    我真得有点怀疑人生,我的网络流模板是不是有大问题,常数大到上天!
    UPD:网络流模板真的有问题,work数组简直就是害人的!去掉!
    代码:

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    const int inf=0x7fffffff;
    int n,m,w,x,y,s,t,ans,sc[25][35],id[25][35];
    int cnt,head[605],work[605],dep[605],in[605],to[400005],nxt[400005],dd[400005];
    bool ck[605];
    vector<int> v[605];
    queue<int> q;
    void addedge(int u,int v){
        in[u]++;
        to[++cnt]=u;
        nxt[cnt]=head[v];
        head[v]=cnt;
    }
    void adde(int u,int v,int d){
        to[++cnt]=v;
        nxt[cnt]=head[u];
        dd[cnt]=d;
        head[u]=cnt;
        to[++cnt]=u;
        nxt[cnt]=head[v];
        dd[cnt]=0;
        head[v]=cnt;
    }
    bool bfs(){
        memset(dep,0,sizeof(dep));
        dep[s]=1;
        while(!q.empty()){
            q.pop();
        }
        q.push(s);
        while(!q.empty()){
            int u=q.front(),v;
            q.pop();
            for(int i=head[u];i;i=nxt[i]){
                v=to[i];
                if(dd[i]&&!dep[v]){
                    dep[v]=dep[u]+1;
                    if(v==t){
                        return true;
                    }
                    q.push(v);
                }
            }
        }
        return false;
    }
    int dfs(int u,int f){
        if(u==t){
            return f;
        }
        int tmp,res=0,v;
        for(int &i=work[u];i&&f;i=nxt[i]){
            v=to[i];
            if(dd[i]&&dep[v]==dep[u]+1&&(tmp=dfs(v,min(f,dd[i])))){
                dd[i]-=tmp;
                dd[i^1]+=tmp;
                f-=tmp;
                res+=tmp;
            }
        }
        if(!res){
            dep[u]=0;
        }
        return res;
    }
    int maxflow(){
        int res=0;
        while(bfs()){
            memcpy(work,head,sizeof(head));
            res+=dfs(s,0x7fffffff);
        }
        return res;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                id[i][j]=(i-1)*m+j;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d%d",&sc[i][j],&w);
                while(w--){
                    scanf("%d%d",&x,&y);
                    x++,y++;
                    v[id[x][y]].push_back(id[i][j]);
                }
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                for(int k=0;k<(int)v[id[i][j]].size();k++){
                    addedge(id[i][j],v[id[i][j]][k]);
                }
                if(j<m){
                    addedge(id[i][j],id[i][j+1]);
                }
            }
        }
        for(int i=1;i<=n*m;i++){
            if(!in[i]){
                q.push(i);
            }
        }
        while(!q.empty()){
            int u=q.front(),v;
            q.pop();
            ck[u]=true;
            for(int i=head[u];i;i=nxt[i]){
                v=to[i];
                in[v]--;
                if(!in[v]){
                    q.push(v);
                }
            }
        }
        s=0;
        t=n*m+1;
        cnt=1;
        memset(head,0,sizeof(head));
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(ck[id[i][j]]){
                    if(sc[i][j]>0){
                        ans+=sc[i][j];
                        adde(s,id[i][j],sc[i][j]);
                    }else if(sc[i][j]<0){
                        adde(id[i][j],t,-sc[i][j]);
                    }
                    for(int k=0;k<(int)v[id[i][j]].size();k++){
                        adde(id[i][j],v[id[i][j]][k],inf);
                    }
                    if(j<m){
                        adde(id[i][j],id[i][j+1],inf);
                    }
                }
            }
        }
        printf("%d
    ",ans-maxflow());
        return 0;
    }
  • 相关阅读:
    帮助应届生、年轻程序员快速成长的12个锦囊<转载>
    曾国藩教您:如何富过三代
    Mvc示例代码调试之二——调试示例讲解
    如何处理婚姻问题
    jQuery对象与dom对象相互转换
    Mvc示例代码调试之一----调试工具及设置(用firebug与vs联合调试)
    Mvc示例之三——用Filter进行简单身份验证
    沟通的艺术
    做bs开发需要学习哪些技术
    我所读过的技术书籍
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476860.html
Copyright © 2011-2022 走看看