码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ1565】【NOI2009】植物大战僵尸 网络流 最大权闭合子图

时间:2018-03-05 19:29:23      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:using   模板   cpp   ret   flow   mat   set   其他   ==   

题目大意

?  给你一个\(n\times m\)的地图,每个格子上都有一颗植物,有的植物能保护其他植物。僵尸从右往左进攻,每吃掉一颗植物就可以得到\(a_{i,j}\)的收益(\(a_{i,j}\)可以是负数)。求僵尸的最大收益

?  \(1\leq n\leq20,1\leq m\leq30\)

题解

?  这种一个东西可以保护另一个东西而且数据范围那么小的题目显然是最大权闭合子图。

?  僵尸从右往左进攻,所以一棵植物可以保护它左边的植物。

?  如果保护关系形成一个环,就都不能选。

?  直接套模板即可。

?  可能需要一些优化

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
struct list
{
    int v[1000010];
    int w[1000010];
    int t[1000010];
    int h[1010];
    int n;
    list()
    {
        memset(h,0,sizeof h);
        n=0;
    }
    void add(int x,int y,int z)
    {
        n++;
        v[n]=y;
        w[n]=z;
        t[n]=h[x];
        h[x]=n;
    }
};
list l,l2;
void add(int x,int y,int z)
{
    l.add(x,y,z);
    l.add(y,x,0);
}
int n,m;
int w[110][110];
int gx[1010];
int gy[1010];
int id(int x,int y)
{
    return (x-1)*m+y;
}
int vis[1010];
int b[1010];
void dfs(int x)
{
    vis[x]=1;
    int i;
    for(i=l2.h[x];i;i=l2.t[i])
    {
        if(!vis[l2.v[i]])
            dfs(l2.v[i]);
        if(b[l2.v[i]]||vis[l2.v[i]]==1)
        {
//          w[gx[x]][gy[x]]=-10000000;
            b[x]=1;
        }
    }
    vis[x]=2;
}
int d[1010];
int S,T;
int c[30][40][30][40];
int bfs()
{
    memset(d,-1,sizeof d);
    queue<int> q;
    q.push(S);
    d[S]=0;
    int x,i;
    while(!q.empty())
    {
        x=q.front();
        q.pop();
        for(i=l.h[x];i;i=l.t[i])
            if(l.w[i]&&d[l.v[i]]==-1)
            {
                d[l.v[i]]=d[x]+1;
                if(l.v[i]==T)
                    return 1;
                q.push(l.v[i]);
            }
    }
    return 0;
}
int op(int x)
{
    return ((x-1)^1)+1;
}
int dfs(int x,int flow)
{
    if(x==T)
        return flow;
    int c,s=0,i;
    for(i=l.h[x];i;i=l.t[i])
        if(l.w[i]&&d[l.v[i]]==d[x]+1)
        {
            c=dfs(l.v[i],min(flow,l.w[i]));
            s+=c;
            flow-=c;
            l.w[i]-=c;
            l.w[op(i)]+=c;
            if(!flow)
                break;
        }
    if(flow)
        d[x]=-1;
    return s;
}
int main()
{
    memset(b,0,sizeof b);
    memset(c,0,sizeof c);
//  freopen("bzoj1565.in","r",stdin);
//  freopen("bzoj1565.out","w",stdout);
    scanf("%d%d",&n,&m);
    S=n*m+1;
    T=S+1;
    int sum=0;
    int i,j,k,o,x,y,u;
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
        {
            scanf("%d",&w[i][j]);
            gx[id(i,j)]=i;
            gy[id(i,j)]=j;
            scanf("%d",&u);
            for(k=1;k<=u;k++)
            {
                scanf("%d%d",&x,&y);
                x++;
                y++;
                c[i][j][x][y]=1;
            }
            if(j>1)
                c[i][j][i][j-1]=1;
            for(x=1;x<=n;x++)
                for(y=1;y<=m;y++)
                    if(c[i][j][x][y])
                        l2.add(id(x,y),id(i,j),0);
        }
    memset(vis,0,sizeof vis);
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            if(!vis[id(i,j)])
                dfs(id(i,j));
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)   
            if(!b[id(i,j)])
            {
                if(w[i][j]>0)
                {
                    sum+=w[i][j];
                    add(S,id(i,j),w[i][j]);
                }
                else
                    add(id(i,j),T,-w[i][j]);
                for(x=1;x<=n;x++)
                    for(y=1;y<=m;y++)
                        if(c[i][j][x][y])
                            if(!b[id(x,y)])
                                add(id(x,y),id(i,j),0x7fffffff);
            }
    int ans=0;
    while(bfs())
        ans+=dfs(S,0x7fffffff);
    printf("%d\n",sum-ans);
    return 0;
}

【BZOJ1565】【NOI2009】植物大战僵尸 网络流 最大权闭合子图

标签:using   模板   cpp   ret   flow   mat   set   其他   ==   

原文地址:https://www.cnblogs.com/ywwyww/p/8510677.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!