• P2805/BZOJ1565 [NOI2009]植物大战僵尸


    每个植物向它能保护的植物连边,矩阵中每个点向它右边相邻的点连边。

    用拓扑排序去除相互保护的植物所成的环,发现将剩余代表保护的边倒置后,答案即为最大权闭合子图。

    代码如下。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int N=1e4+10,M=1e6+10,inf=0x3f3f3f3f;
    int n,m,s,t,ans,tot=1,a[N],d[N],v[N],deg[N],head[N],ver[M],next[M],edge[M];vector<int> g[N];queue<int> q;
    inline ll read(){
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void add(int x,int y,int z){
        ver[++tot]=y;edge[tot]=z;next[tot]=head[x];head[x]=tot;
        ver[++tot]=x;edge[tot]=0;next[tot]=head[y];head[y]=tot;
    }
    inline bool bfs(){
        memset(d,0,sizeof(d));
        queue<int> q;d[s]=1;q.push(s);
        while(q.size()){
            int x=q.front();q.pop();
            for(int i=head[x];i;i=next[i]){
                int y=ver[i],z=edge[i];
                if(d[y]||!z) continue;
                d[y]=d[x]+1;q.push(y);
                if(y==t) return 1;
            }
        }
        return 0;
    }
    inline int dinic(int x,int flow){
        if(x==t) return flow;
        int rest=flow;
        for(int i=head[x];i&&rest;i=next[i]){
            int y=ver[i],z=edge[i];
            if(d[y]!=d[x]+1||!z) continue;
            int k=dinic(y,min(z,rest));
            if(!k) d[y]=0;
            else edge[i]-=k,edge[i^1]+=k,rest-=k;
        }
        return flow-rest;
    }
    int main(){
        n=read();m=read();s=n*m;t=s+1;
        for(int i=0;i<s;i++){
            a[i]=read();int p=read();
            while(p--){
                int x=read(),y=read();
                g[i].push_back(x*m+y);deg[x*m+y]++;
            }
        } 
        for(int i=0;i<n;i++){
            for(int j=1;j<m;j++){
                g[i*m+j].push_back(i*m+j-1);deg[i*m+j-1]++;
            }
        }
        for(int i=0;i<s;i++) if(!deg[i]) q.push(i),v[i]=1;
        while(q.size()){
            int x=q.front();q.pop();
            for(int i=0;i<g[x].size();i++){
                int y=g[x][i];
                if(!v[y]&&!--deg[y]) q.push(y),v[y]=1; 
            }
        }
        for(int x=0;x<s;x++){
            if(!v[x]) continue;
            for(int i=0;i<g[x].size();i++){
                int y=g[x][i];if(!v[y]) continue;
                add(y,x,inf);
            }
            if(a[x]>0) add(s,x,a[x]),ans+=a[x];
            else if(a[x]<0) add(x,t,-a[x]);
        }
        while(bfs()) ans-=dinic(s,inf);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    PHP IDE NetBeans代码主题和除掉竖线解决方案
    初识Python
    从LazyPhp说起
    从Pycharm说起
    准备系统地研究一下"高性能网站开发",挑战很大,希望能坚持到底!
    IIS日志分析[资源]
    见一好东西:Threaded WebDownload class with Progress Callbacks
    ASP.net Application 中使用域用户登录
    看图找错
    汉字转拼音缩写的函数(C#)
  • 原文地址:https://www.cnblogs.com/xtkm/p/10847924.html
Copyright © 2020-2023  润新知