1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #define M 1000 7 #define N 360000 8 #define inf 2139062143 9 using namespace std; 10 int cnt=1,n,m,S,T,d[M],q[M],f[M],head[M],next[N],u[N],v[N],a[M],head1[M],next1[N],u1[N],du[N],cnt1; 11 int ans,sum; 12 bool bfs() 13 { 14 memset(d,0,sizeof(d)); 15 int h=0,t=1; 16 q[1]=S; 17 d[S]=1; 18 for(;h<t;) 19 { 20 h++; 21 int p=q[h]; 22 for(int i=head[p];i;i=next[i]) 23 if(!d[u[i]]&&v[i]) 24 { 25 d[u[i]]=d[p]+1; 26 if(d[T]) 27 return 1; 28 t++; 29 q[t]=u[i]; 30 } 31 } 32 return 0; 33 } 34 int dinic(int s,int f) 35 { 36 if(s==T) 37 return f; 38 int rest=f; 39 for(int i=head[s];i&&rest;i=next[i]) 40 if(v[i]&&d[u[i]]==d[s]+1) 41 { 42 int now=dinic(u[i],min(rest,v[i])); 43 if(!now) 44 d[u[i]]=0; 45 v[i]-=now; 46 v[i^1]+=now; 47 rest-=now; 48 } 49 return f-rest; 50 } 51 void jia1(int a1,int a2,int a3) 52 { 53 cnt++; 54 next[cnt]=head[a1]; 55 head[a1]=cnt; 56 u[cnt]=a2; 57 v[cnt]=a3; 58 return; 59 } 60 void jia(int a1,int a2,int a3) 61 { 62 jia1(a1,a2,a3); 63 jia1(a2,a1,0); 64 return; 65 } 66 int main() 67 { 68 scanf("%d%d",&n,&m); 69 S=0; 70 T=n*m+1; 71 for(int i=1;i<=n;i++) 72 for(int j=1;j<=m;j++) 73 { 74 int a2,a3,a4,a5,a6; 75 a6=(i-1)*m+j; 76 scanf("%d%d",&a[a6],&a2); 77 for(int k=1;k<=a2;k++) 78 { 79 scanf("%d%d",&a3,&a4); 80 a3++; 81 a4++; 82 a5=(a3-1)*m+a4; 83 cnt1++; 84 next1[cnt1]=head1[a6]; 85 head1[a6]=cnt1; 86 du[a5]++; 87 u1[cnt1]=a5; 88 } 89 } 90 for(int i=1;i<=n;i++) 91 for(int j=1;j<m;j++) 92 { 93 int a1=(i-1)*m+j,a2=(i-1)*m+j+1; 94 cnt1++; 95 next1[cnt1]=head1[a2]; 96 head1[a2]=cnt1; 97 du[a1]++; 98 u1[cnt1]=a1; 99 } 100 int h=0,t=0; 101 for(int i=1;i<=n*m;i++) 102 if(!du[i]) 103 q[++t]=i; 104 for(;h<t;) 105 { 106 h++; 107 for(int i=head1[q[h]];i;i=next1[i]) 108 { 109 du[u1[i]]--; 110 if(!du[u1[i]]) 111 q[++t]=u1[i]; 112 } 113 } 114 for(int i=1;i<=n;i++) 115 for(int j=1;j<=m;j++) 116 if(!du[(i-1)*m+j]) 117 { 118 int a1=(i-1)*m+j; 119 if(a[a1]>0) 120 { 121 jia(a1,T,a[a1]); 122 sum+=a[a1]; 123 } 124 else 125 jia(S,a1,-a[a1]); 126 for(int k=head1[a1];k;k=next1[k]) 127 if(!du[u1[k]]) 128 jia(a1,u1[k],inf); 129 } 130 for(;bfs();) 131 ans+=dinic(S,inf); 132 printf("%d\n",sum-ans); 133 return 0; 134 }
首先我们要把互相保护的去掉,在右边的肯定保护它左边的,还有题目中原先的保护条件 进行建边,拓扑排序去掉永远吃不掉的。然后把所有边反向就是一个最大权闭合子图,正权点向
汇点建边,容量为权值。源点向负权点建边,容量为权值相反数,原图中的边容量为inf,答案为正权值和减去最小割。