BZOJphp
首先仍是給棋盤進行黑白染色,而後對於特殊邊左右兩側的格子單獨拎出來考慮。
爲了和其餘格子區分,咱們把兩側的這兩個格子染成灰色。
因而一個不合法的狀態就是兩個相鄰的灰色點若是還和一個其餘的點相連就是非法的。
咱們先把黑白點分開,源點連向黑點,匯點連向白點,邊權是刪去這個點的代價。
由於灰點能夠兩兩配對,非兩兩配對之間的沒有影響,而後全部黑點連向對應的灰點,另外一半灰點連向對應的白點。而要刪去一組不合法的要麼刪去一個灰點,要麼刪去全部黑點或者全部白點,而連向源匯已經處理了刪去全部黑點或者白點,因此只須要考慮刪去一個灰點,顯然刪哪一個都是同樣的因此兩個匹配的灰點之間連一條權值爲兩個點權值較小值的邊。
這樣子最小割就是答案。ios
#include<iostream> #include<cstdio> #include<vector> #include<queue> #include<map> using namespace std; #define MAX 100100 const int inf=2e9; inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } struct Line{int v,next,w;}e[MAX*20]; int h[MAX],cnt=2; inline void Add(int u,int v,int w) { e[cnt]=(Line){v,h[u],w};h[u]=cnt++; e[cnt]=(Line){u,h[v],0};h[v]=cnt++; } int S,T,cur[MAX],level[MAX]; queue<int> Q; bool bfs() { for(int i=S;i<=T;++i)level[i]=0; Q.push(S);level[S]=1; while(!Q.empty()) { int u=Q.front();Q.pop(); for(int i=h[u];i;i=e[i].next) if(e[i].w&&!level[e[i].v]) level[e[i].v]=level[u]+1,Q.push(e[i].v); } return level[T]; } int dfs(int u,int flow) { if(u==T||!flow)return flow; int ret=0; for(int &i=cur[u];i;i=e[i].next) { int v=e[i].v,d; if(e[i].w&&level[v]==level[u]+1) { d=dfs(v,min(flow,e[i].w)); ret+=d;flow-=d; e[i].w-=d;e[i^1].w+=d; if(!flow)break; } } if(!ret)level[u]=0; return ret; } int Dinic() { int ret=0; while(bfs()) { for(int i=S;i<=T;++i)cur[i]=h[i]; ret+=dfs(S,inf); } return ret; } map<pair<int,int>,int> M; int col[MAX]; int d[4][2]={1,0,0,1,-1,0,0,-1}; int C,R,n,X[MAX],Y[MAX],W[MAX]; bool check(int x,int y) { if(x&1)return y%4==1||y%4==2; else return y%4==3||y%4==0; } int main() { R=read();C=read();n=read(); for(int i=1;i<=n;++i) { Y[i]=read();X[i]=read();W[i]=read(); M[make_pair(X[i],Y[i])]=i; if((X[i]+Y[i]+1)&1)col[i]=check(X[i],Y[i])?3:1; else col[i]=check(X[i],Y[i])?2:0; } S=0;T=n+1; for(int i=1;i<=n;++i) if(col[i]==0)Add(i,T,W[i]); else if(col[i]==1)Add(S,i,W[i]); else if(col[i]==2) for(int j=0;j<4;++j) { int x=X[i]+d[j][0],y=Y[i]+d[j][1]; if(M.find(make_pair(x,y))==M.end())continue; int d=M[make_pair(x,y)]; if(col[d]==1)Add(d,i,inf); else if(col[d]==3)Add(i,d,min(W[d],W[i])); } else if(col[i]==3) for(int j=0;j<4;++j) { int x=X[i]+d[j][0],y=Y[i]+d[j][1]; if(M.find(make_pair(x,y))==M.end())continue; int d=M[make_pair(x,y)]; if(col[d]==0)Add(i,d,inf); } printf("%d\n",Dinic()); return 0; }