题面:
思路:
这道题明显可以看出来有依赖关系
那么根据依赖(保护)关系建图:如果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\n",tot-ans); 142 }