zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    【LibreOJ】#6257. 「CodePlus 2017 12 月赛」可做题2
    【Atcoer】ARC088 E
    【Atcoder】ARC088 D
    【CodeForces】671 D. Roads in Yusland
    【CodeForces】671 B. Robin Hood
    【CodeForces】671 C. Ultimate Weirdness of an Array
    【CodeForces】679 A. Bear and Prime 100
    【CodeForces】679 B. Bear and Tower of Cubes
    【BZOJ】3262: 陌上花开
    【CodeForces】899 F. Letters Removing
  • 原文地址:https://www.cnblogs.com/xtkm/p/10847924.html
Copyright © 2011-2022 走看看