bzoj4808: 马 & bzoj3175: [Tjoi2013]攻击装置 (黑白染色+最小割)
bzoj4808: 马 & bzoj3175: [Tjoi2013]攻击装置
题目:传送门
简要题意:
和n皇后问题差不多,但是这里是每个棋子走日子,而且有些格子不能放棋子。求最多能放多少个棋子。
题解:
双倍经验好评
之前看过机房神犇做...有点印象是最小割。
但是直接割的话不会...要应用到黑白染色:
最开始我想递归染色,也就是取一个开始染,然后递归下去...
波老师说会错ORZ...因为感觉递归的情况不好掌握,有可能会重复染色...
结果有一个肥肠巧妙的方法...直接相邻的染为不同颜色
之后就会惊奇的发现,woc当前格子能跳到的格子一定是和自己异色的!
那就最小割咯
st连白的,黑的连ed,互相能到达的黑色和白色连inf
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #define inf 999999999 7 using namespace std; 8 struct node 9 { 10 int x,y,c,next,other; 11 }a[1110000];int len,last[410000]; 12 void ins(int x,int y,int c) 13 { 14 int k1,k2; 15 k1=++len; 16 a[len].x=x;a[len].y=y;a[len].c=c; 17 a[len].next=last[x];last[x]=len; 18 19 k2=++len; 20 a[len].x=y;a[len].y=x;a[len].c=0; 21 a[len].next=last[y];last[y]=len; 22 23 a[k1].other=k2; 24 a[k2].other=k1; 25 } 26 int st,ed,head,tail,n,m; 27 int list[410000],h[410000]; 28 bool bt_h() 29 { 30 memset(h,0,sizeof(h));h[st]=1; 31 list[1]=st;head=1;tail=2; 32 while(head!=tail) 33 { 34 int x=list[head]; 35 for(int k=last[x];k;k=a[k].next) 36 { 37 int y=a[k].y; 38 if(!h[y] && a[k].c) 39 { 40 h[y]=h[x]+1; 41 list[tail++]=y; 42 } 43 } 44 head++; 45 } 46 if(h[ed])return true; 47 return false; 48 } 49 int find_flow(int x,int flow) 50 { 51 int s=0,t; 52 if(x==ed)return flow; 53 for(int k=last[x];k;k=a[k].next) 54 { 55 int y=a[k].y; 56 if(h[y]==h[x]+1 && a[k].c && s<flow) 57 { 58 s+=t=find_flow(y,min(a[k].c,flow-s)); 59 a[k].c-=t;a[a[k].other].c+=t; 60 } 61 } 62 if(!s)h[x]=0; 63 return s; 64 } 65 int mp[210][210],d[210][210]; 66 bool f[210][210]; 67 const int dx[9]={0,1,1,-1,-1,-2,-2,2,2}; 68 const int dy[9]={0,2,-2,2,-2,-1,1,-1,1}; 69 int main() 70 { 71 scanf("%d%d",&n,&m);int s=0,sum=0; 72 for(int i=1;i<=n;i++) 73 for(int j=1;j<=m;j++) 74 { 75 scanf("%d",&mp[i][j]),d[i][j]=++s; 76 if(mp[i][j]!=1)sum++; 77 } 78 st=n*m+1;ed=st+1; 79 memset(f,0,sizeof(f)); 80 for(int i=1;i<=n;i++) 81 { 82 for(int j=1;j<=m;j++) 83 { 84 if(i==1 && j==1)f[i][j]=1; 85 else if(i!=1 && j==1) 86 { 87 if(f[i][j]==f[i-1][j]) 88 f[i][j]^=1; 89 } 90 else 91 { 92 if(f[i][j]==f[i][j-1]) 93 f[i][j]^=1; 94 } 95 } 96 } 97 for(int i=1;i<=n;i++) 98 for(int j=1;j<=m;j++) 99 { 100 if(mp[i][j]!=1) 101 { 102 if(f[i][j])ins(st,d[i][j],1); 103 else ins(d[i][j],ed,1); 104 } 105 } 106 for(int i=1;i<=n;i++) 107 for(int j=1;j<=m;j++) 108 if(mp[i][j]!=1 && f[i][j]) 109 for(int k=1;k<=8;k++) 110 { 111 int ii=i+dx[k],jj=j+dy[k]; 112 if(ii>=1 && ii<=n && jj>=1 && jj<=m) 113 if(mp[ii][jj]!=1) 114 if(!f[ii][jj]) 115 ins(d[i][j],d[ii][jj],inf); 116 } 117 int ans=0; 118 while(bt_h())ans+=find_flow(st,inf); 119 printf("%d\n",sum-ans); 120 return 0; 121 }