二分图匹配。。先黑白染色,若黑白点能攻击就连边,答案就是所有位置数-最大匹配数-不能放的点数
终于见识到黑白染色的作用,以前从来不鸟染色直接做。。
话说这个匈牙利居然比dinic快那么多。。。这是数据问题还是复杂度的问题。。。不都是龟速么orz
以前一直用网络流代替二分图来做,不想学匈牙利。。算了今天学一下。。
1 #include<bits/stdc++.h> 2 #define inc(i,l,r) for(i=l;i<=r;i++) 3 #define dec(i,l,r) for(i=l;i>=r;i--) 4 #define mem(a) memset(a,0,sizeof(a)) 5 #define inf 1e9 6 #define ll long long 7 #define succ(x) (1<<x) 8 #define NM 100000+5 9 #define nm 1000000 10 using namespace std; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 14 while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); 15 return x*f; 16 } 17 struct edge{ 18 int t; 19 edge *next; 20 }e[nm],*h[NM]; 21 const int dir[8][2]={-1,-2,-2,-1,1,-2,2,-1,-1,2,-2,1,1,2,2,1}; 22 int match[NM],n,ans,s,i,b[205][205],j,k,_x,_y,v[NM]; 23 char a[205][205]; 24 queue<int >q; 25 void add(int x,int y){ 26 e[++s].t=y;e[s].next=h[x];h[x]=e+s; 27 } 28 bool dfs(int x){ 29 for(edge *j=h[x];j;j=j->next) 30 if(v[j->t]!=b[i][k]){ 31 v[j->t]=b[i][k]; 32 if(!match[j->t]||dfs(match[j->t])){ 33 match[j->t]=x; 34 return true; 35 } 36 } 37 return false; 38 } 39 int main(){ 40 scanf("%d",&n); 41 inc(i,0,n-1)scanf("%s",a[i]); 42 inc(i,0,n-1) 43 inc(j,0,n-1) 44 if(a[i][j]=='0')b[i][j]=++ans; 45 inc(i,0,n-1) 46 inc(j,0,n-1) 47 if(b[i][j]){ 48 if((i+j)&1) 49 inc(k,0,7){ 50 _x=i+dir[k][0];_y=j+dir[k][1]; 51 if(_x>=0&&_x<n&&_y>=0&&_y<n&&b[_x][_y]) 52 add(b[i][j],b[_x][_y]); 53 } 54 } 55 inc(i,0,n-1) 56 inc(k,0,n-1) 57 if(b[i][k]&&dfs(b[i][k]))ans--; 58 printf("%d\n",ans); 59 return 0; 60 }