比较裸的二分图最大独立集,不过复杂度是不对的,匈牙利算法跑得太快了,然后要注意为了不超时,每次匈牙利的时候不能清空vis的数组,而是把它进行标记。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #define maxn 40010 #define maxm 8*40010 using namespace std; int head[maxn],next[maxm],to[maxm]; int lk[maxn]; int a[210][210]; int dx[4]={1,1,2,2}; int dy[4]={2,-2,1,-1}; int n,m,num,cnt,ans,T; int vis[maxn]; char s[210]; bool find(int x) { for (int p=head[x];p;p=next[p]) if (vis[to[p]]!=T) { vis[to[p]]=T; if (!lk[to[p]] || find(lk[to[p]])) { lk[to[p]]=x; return 1; } } return 0; } void addedge(int x,int y) { num++;to[num]=y;next[num]=head[x];head[x]=num; } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%s",s+1); for (int j=1;j<=n;j++) { if (s[j]=='0') a[i][j]=++cnt; else a[i][j]=0; } } for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (a[i][j]) { for (int k=0;k<4;k++) { int x=i+dx[k],y=j+dy[k]; if (x<1 || x>n || y<1 || y>n) continue; if (a[x][y]) addedge(a[i][j],a[x][y]),addedge(a[x][y],a[i][j]); } } for (int i=1;i<=cnt;i++) { T++; if (find(i)) ans++; } printf("%d\n",cnt-ans/2); return 0; }