[NOI2009]植物大战僵尸

题链

SOL:最大权闭合子图,记得判环,边拓扑时要反向存,正反的答案不一样。

我们考虑一个环,其每一个点都向中点连边,正向的话中点时判环中的,反向就判在环外了。

#include<bits/stdc++.h>
using namespace std;
template <class T>
#define gc getchar
#define sight(c) ('0'<=c&&c<='9')
inline void read(T &x){
    static int b; static char c;
    for (b=1,c=gc();!sight(c);c=gc()) if (c=='-') b=-1;
    for (x=0;sight(c);c=gc()) x=x*10+c-48;
    x*=b;
}
struct maxflow{
     #define N 100007
     #define M 1000007
     #define inf (1<<29)
     #define eho(x) for (int i=head[x];i;i=net[i])
     #define Eho(x) for (int &i=hea[x];i;i=net[i])
     int n,s,t,head[N],hea[N],net[M],fall[M],tot,gap[N],d[N],cost[M],p[N],be,ed,x,ret;
     maxflow() {tot=1;memset(head,0,sizeof head);}
     inline void clear() {
         tot=1; memset(head,0,sizeof head);}
     inline void add(int x,int y,int z){
         fall[++tot]=y; net[tot]=head[x]; head[x]=tot; cost[tot]=z;
     }
     inline void adds(int x,int y,int z){
         add(x,y,z); add(y,x,0);
     }
     void init() {
         memset(gap,0,sizeof gap); memset(d,0,sizeof d);
         ++gap[d[t]=1];
         memcpy(hea,head,sizeof hea);
         p[be=ed=1]=t; 
         while (be<=ed) {
             x=p[be++];
             eho(x) if (!d[fall[i]]) ++gap[d[fall[i]]=d[x]+1],p[++ed]=fall[i];
         }
     }
     int get(int x,int fl){
         if (x==t) return fl; if (!fl) return 0;
         int flow=0,tmp;
         Eho(x) if (d[x]==d[fall[i]]+1&&(tmp=get(fall[i],min(fl,cost[i])))) {
             flow+=tmp; fl-=tmp; cost[i]-=tmp; cost[i^1]+=tmp;
             if (!fl) return flow;
        } 
        if (!(--gap[d[x]])) d[s]=n+1;
        ++gap[++d[x]]; hea[x]=head[x];
        return flow;
     }
     int isap(int x,int y,int siz){
         s=x; t=y; n=siz;
         init();
         ret=get(s,inf);
         while (d[s]<=n) ret+=get(s,inf);
         return ret;
     }
}G;
#define r(x,y) (x*m+y+1)
int n,m,tot,head[N],fall[M],net[M],q[N],be,ed,mp[N],p,x,y,in[N],v[N],sum;
inline void add(int x,int y){fall[++tot]=y; net[tot]=head[x]; head[x]=tot; }
int main () {
//    freopen("a.in","r",stdin);
    read(n); read(m);
    for(int i=1;i<=n*m;i++) {
        read(mp[i]); read(p);
        while (p--) {
            read(x); read(y);
//            add(r(x,y),i); in[i]++;
            add(i,r(x,y)); in[r(x,y)]++;
        }
        if (i%m) add(i+1,i),in[i]++;
//        add(i,i+1),in[i+1]++;
    }
    for (int i=n*m;i;i--) if (!in[i]) q[ed++]=i;
    while (be<ed) {
        x=q[be++]; v[x]=1;
        eho(x) if (!(--in[fall[i]])) q[ed++]=fall[i];
    }
    for (int x=1;x<=n*m;x++) if (v[x]){
        if (mp[x]>0) G.adds(0,x,mp[x]),sum+=mp[x]; else G.adds(x,n*m+1,-mp[x]);
        eho(x) if(v[fall[i]]) G.adds(fall[i],x,inf);
    } 
    printf("%d",sum-G.isap(0,n*m+1,n*m+2));
}

 

posted @ 2018-03-01 20:18  泪寒之雪  阅读(234)  评论(0编辑  收藏  举报