常见套路:棋盘黑白染色,就变成了一张二分图
然后如果选了黑点,四周的白点就不能选了,也是最小割的套路。先把所有价值加起来,再减掉一个最少的不能选的价值,也就是割掉表示不选
建边(S,黑点i,v[i]),(黑点i,i四周的白点,inf),(白点j,T,v[j])
(黑点还是白点,你必须要割一个...)
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=100*100+10,maxm=100*100*20+5,inf=1e9; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*neg; 13 } 14 15 struct Edge{ 16 int a,b,l,ne; 17 }eg[maxm]; 18 int egh[maxn],ect=1,cur[maxn]; 19 int N,M,S,T; 20 int dep[maxn]; 21 queue<int> q; 22 23 inline void adeg(int a,int b,int c){ 24 // printf("!%d %d %d\n",a,b,c); 25 eg[++ect].a=a,eg[ect].b=b,eg[ect].l=c,eg[ect].ne=egh[a],egh[a]=ect; 26 eg[++ect].a=b,eg[ect].b=a,eg[ect].l=0,eg[ect].ne=egh[b],egh[b]=ect; 27 } 28 29 inline bool bfs(){ 30 CLR(dep,0);CLR(cur,-1); 31 dep[S]=1,q.push(S); 32 while(!q.empty()){ 33 int p=q.front();q.pop(); 34 for(int i=egh[p];i;i=eg[i].ne){ 35 int b=eg[i].b; 36 if(!eg[i].l||dep[b]) continue; 37 dep[b]=dep[p]+1; 38 q.push(b); 39 } 40 } 41 return dep[T]; 42 } 43 44 int dinic(int x,int y){ 45 if(x==T) return y; 46 if(cur[x]==-1) cur[x]=egh[x]; 47 int tmp=y; 48 for(int &i=cur[x];i;i=eg[i].ne){ 49 int b=eg[i].b; 50 if(dep[b]!=dep[x]+1||!eg[i].l) continue; 51 int re=dinic(b,min(tmp,eg[i].l)); 52 tmp-=re,eg[i].l-=re,eg[i^1].l+=re; 53 if(!tmp) break; 54 }return y-tmp; 55 } 56 int main(){ 57 //freopen("","r",stdin); 58 int i,j,k; 59 M=rd(),N=rd(); 60 S=N*M+1,T=N*M+2; 61 int ans=0; 62 for(i=1;i<=M;i++){ 63 for(j=1;j<=N;j++){ 64 int id=(i-1)*N+j; 65 k=rd();ans+=k; 66 if(((i&1)&&(j&1))||(!(i&1)&&!(j&1))){ 67 adeg(S,id,k); 68 if(j<N) adeg(id,id+1,inf); 69 if(j>1) adeg(id,id-1,inf); 70 if(i<M) adeg(id,id+N,inf); 71 if(i>1) adeg(id,id-N,inf); 72 }else adeg(id,T,k); 73 } 74 } 75 while(bfs()) ans-=dinic(S,inf); 76 printf("%d\n",ans); 77 return 0; 78 }