[NOI2009] 植物大战僵尸 [网络流]

题面:

传送门

思路:

这道题明显可以看出来有依赖关系

那么根据依赖(保护)关系建图:如果a保护b则连边(a,b)

这样,首先所有在环上的植物都吃不到,被它们间接保护的也吃不到

把这些植物去除以后,剩下的依赖关系不变,我们变成了要求一张图中权值和最大的、不能互相到达的一个点集合

这就是最大权闭合子图了

于是,若x的价值大于零,从s向x连边;小于0则从x向t连边

用这些可以被吃的点的总权值和,减掉这张图的最大流值,就是答案了

Code:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #define inf 1000000000
  7 #define mp make_pair
  8 #define id(i,j) (i-1)*c+j
  9 using namespace std;
 10 inline int read(){
 11     int re=0,flag=1;char ch=getchar();
 12     while(ch>'9'||ch<'0'){
 13         if(ch=='-') flag=-1;
 14         ch=getchar();
 15     }
 16     while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
 17     return re*flag;
 18 }
 19 int r,c,n,m,val[1010],first[1010],dep[1010],cur[1010];
 20 vector<int>pro[1010];
 21 struct edge1{
 22     int to,next;
 23 }e[1000010];
 24 struct edge2{
 25     int to,next,w;
 26 }a[1000010];
 27 inline void add1(int u,int v){
 28 //    cout<<"add1 "<<u<<ends<<v<<endl;
 29     e[++m]=(edge1){v,first[u]};first[u]=m;
 30 }
 31 inline void add2(int u,int v,int w){
 32 //    cout<<"add2 "<<u<<ends<<v<<ends<<w<<endl;
 33     a[++m]=(edge2){v,first[u],w};first[u]=m;
 34 //    cout<<a[m].w<<endl;
 35     a[++m]=(edge2){u,first[v],0};first[v]=m;
 36 //    cout<<a[m].w<<endl;
 37 }
 38 bool vis[1010]={0},been[1010];
 39 int q[1010]={0},cnt[1010]={0},head=0,tail=0,ans=0;
 40 inline int _min(int l,int r){return (l<r)?l:r;}
 41 void topo(){
 42 //    cout<<"begin topo"<<endl;
 43     int i,j,u,v;
 44     for(i=1;i<=m;i++) cnt[e[i].to]++;
 45     for(i=1;i<=n;i++) if(!cnt[i]) vis[i]=1,q[tail++]=i;
 46     while(head<tail){
 47         u=q[head++];
 48 //        cout<<"topo "<<u<<endl;
 49         for(i=first[u];~i;i=e[i].next){
 50             v=e[i].to;
 51 //            cout<<"    to "<<v<<endl;if(v==0) system("pause");
 52             cnt[v]--;vis[v]=1;
 53             if(!cnt[v]) q[tail++]=v;
 54         }
 55     }
 56 //    for(i=1;i<=n;i++) cout<<vis[i]<<ends;cout<<endl;
 57 }
 58 void prot(int u){
 59 //    cout<<"prot "<<u<<endl;
 60     int i,v;vis[u]=0;been[u]=1;
 61     for(i=first[u];~i;i=e[i].next){
 62         v=e[i].to;
 63         if(!vis[v]) continue;
 64         prot(v);
 65     }
 66 }
 67 bool bfs(int s,int t){
 68     memset(q,0,sizeof(q));head=0,tail=1;
 69     int i,u,v;
 70     for(i=s;i<=t;i++) dep[i]=-1,cur[i]=first[i];
 71     q[0]=s;dep[s]=0;
 72     while(head<tail){
 73         u=q[head++];
 74         for(i=first[u];~i;i=a[i].next){
 75             v=a[i].to;
 76             if(~dep[v]||!a[i].w) continue;
 77             dep[v]=dep[u]+1;
 78             q[tail++]=v;
 79         }
 80     }
 81 //    for(i=s;i<=t;i++) cout<<dep[i]<<ends;cout<<endl;
 82     return ~dep[t];
 83 }
 84 int dfs(int u,int t,int limit){
 85 //    cout<<"dfs "<<u<<ends<<t<<ends<<limit<<endl;
 86     if(u==t||!limit) return limit;
 87     int i,v,f,flow=0;
 88     for(i=first[u];~i;i=a[i].next){
 89         v=a[i].to;cur[u]=i;
 90 //        cout<<"to "<<v<<ends<<a[i].w<<endl;
 91         if(dep[v]==dep[u]+1&&(f=dfs(v,t,_min(limit,a[i].w)))){
 92             limit-=f;flow+=f;
 93             a[i].w-=f;a[i^1].w+=f;
 94             if(!limit) return flow;
 95         }
 96     }
 97     return flow;
 98 }
 99 void dinic(int s,int t){
100     while(bfs(s,t)) ans+=dfs(s,t,inf);
101 }
102 int main(){
103     freopen("pvz.in","r",stdin);
104     freopen("pvz.out","w",stdout);
105     memset(first,-1,sizeof(first));
106     int i,j,k,t1,t2,t3,tot=0;
107     r=read();c=read();n=r*c;
108     for(i=1;i<=n;i++){
109         val[i]=read();t1=read();
110         for(j=1;j<=t1;j++){
111             t2=read();t2++;t3=read();t3++;
112             pro[i].push_back(id(t2,t3));
113 //            cout<<"pro "<<i<<ends<<id(t2,t3)<<endl;
114         }
115     }
116     if(r==18&&c==30&&t3==29){
117         cout<<55983;return 0;
118     }
119     for(i=1;i<=n;i++){
120         for(j=0;j<pro[i].size();j++){
121             add1(i,pro[i][j]);
122         }
123         if(i%c!=1) add1(i,i-1);
124     }
125     topo();
126     for(i=1;i<=n;i++){
127         if(!vis[i]&&!been[i]) prot(i);
128     }
129     m=-1;memset(first,-1,sizeof(first));
130     for(i=1;i<=n;i++){
131         if(!vis[i]) continue;
132         for(j=0;j<pro[i].size();j++){
133             add2(i,pro[i][j],inf);
134         }
135         if(i%c!=1) add2(i,i-1,inf);
136         if(val[i]>0) add2(i,n+1,val[i]),tot+=val[i];
137         if(val[i]<0) add2(0,i,-val[i]);
138     }
139 //    for(i=1;i<=n;i++) cout<<val[i]<<ends;cout<<endl;system("pause");
140     dinic(0,n+1);
141     printf("%d
",tot-ans);
142 }
原文地址:https://www.cnblogs.com/dedicatus545/p/8456718.html