NOI2009植物大战僵尸题解

来源:互联网 发布:oracle数据库好学吗 编辑:程序博客网 时间:2024/05/05 12:44

因为a能保护b,所以杀b必须先杀a

那么就构成了最大权闭合子图的模型

注意会存在环,这个时候环内的所有点都不可取

用一个拓扑排序把环去掉,然后跑最大权闭合子图

注意在网络流中会出现没有后继的点,我原来的sb模板写的是不能回流的……

然后还有就是编号从零开始(因为这个调了一个星期……-.-

代码:

#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
struct lwn{
    int u,v,flow,cap;
} a[360050];
int tot,n,i,m,j,hyy;
vector<int> g[360050];
int num[650];
int d[650];
int p[650];
int in[650];
int cur[650];
vector<int> g2[360050];
int c[650];
void init(int x,int y,int z)
{
    a[++tot].u=x;
    a[tot].v=y;
    a[tot].flow=0;
    a[tot].cap=z;
    g[x].push_back(tot);
}
int maxflow(int s,int t)
{
    int x=s;
    int ans=0;
    num[0]=n+1;
    while (d[s]<n+1){
        if (x==t){
            int jb=2000000000;
            while (x!=s){
                jb=min(jb,a[p[x]].cap-a[p[x]].flow);
                x=a[p[x]].u;
            }
            x=t;
            ans+=jb;
            while (x!=s){
                a[p[x]].flow+=jb;
                a[(p[x]+tot) % (tot << 1)].flow-=jb;
                x=a[p[x]].u;
            }
        }
        bool zw=true;
        for (i=cur[x];i<g[x].size();i++) if (!in[a[g[x][i]].v] && d[x]==d[a[g[x][i]].v]+1 && a[g[x][i]].cap>a[g[x][i]].flow){
            p[a[g[x][i]].v]=g[x][i];
            zw=false;
            cur[x]=i;
            x=a[g[x][i]].v;
            break;
        }
        if (zw){
            cur[x]=0;
            int jb=n+1;
            for (i=0;i<g[x].size();i++) if (!in[a[g[x][i]].v] && a[g[x][i]].cap>a[g[x][i]].flow){
                jb=min(jb,d[a[g[x][i]].v]+1);
            }
            if (--num[d[x]]==0) return ans;
            num[d[x]=jb]++;
            if (x!=s){
                x=a[p[x]].u;
            }
        }
    }
    return ans;
}
int main()
{
//freopen("input.txt","r",stdin);
    scanf("%d%d",&n,&m);
    tot=0;
    for (i=0;i<n;i++)
    for (j=0;j<m;j++){
        if (j!=m-1) init(i*m+j,i*m+j+1,200000000);
    }
    int sum=0;
    for (i=0;i<n*m;i++){
        int x,y,z;
        scanf("%d",&c[i]);
        if (c[i]>0){
            init(n*m,i,c[i]);
            sum+=c[i];
        }
        else init(i,n*m+1,-c[i]);
        scanf("%d",&x);
        while (x--){
            scanf("%d%d",&y,&z);
            init(y*m+z,i,200000000);
        }
    }
    for (i=1;i<=tot;i++){
        a[i+tot].u=a[i].v;
        a[i+tot].v=a[i].u;
        a[i+tot].flow=0;
        a[i+tot].cap=0;
        g[a[i].v].push_back(i+tot);
        if (a[i].cap==200000000){
        g2[a[i].v].push_back(a[i].u);
       in[a[i].u]++;
        }
    }
    queue<int> q;
    for (i=0;i<n*m;i++) if (!in[i]) q.push(i);
    while (!q.empty()){
    int hyy=q.front();
    q.pop();
    for (i=0;i<g2[hyy].size();i++){
    in[g2[hyy][i]]--;
    if (!in[g2[hyy][i]]) q.push(g2[hyy][i]);
    }
    }
    for (i=0;i<n*m;i++) if (in[i] && c[i]>0){
    sum-=c[i];
    }
    n=n*m+1;
    printf("%d\n",sum-maxflow(n-1,n));
    return 0;
}

0 0
原创粉丝点击