bzoj 3175 攻击装置 | 二分图最大独立集
2015-11-16 10:40
417 查看
显然日字是从黑点到白点,所以黑白染色做独立集就行了。注意连边的时候要让它先和位于它下面的点匹配,因为下面的点未匹配的概率更大,dfs的深度也更小。我开始先匹配的上面的点,t了。
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #define md #define ll long long #define inf (int) 1e9 #define eps 1e-8 #define N 210 #define M 40010 using namespace std; struct yts { int x,t,ne; } e[8*M]; int g ; char st ; int v[M],vis[M],link[M]; int lx[8]={-1,-1,-2,-2,1,1,2,2,},ly[8]={2,-2,1,-1,2,-2,1,-1}; int num=0; void put(int x,int y) { num++; e[num].x=x; e[num].t=y; e[num].ne=v[x]; v[x]=num; } bool dfs(int x,int tm) { if (vis[x]==tm) return 0; vis[x]=tm; for (int i=v[x];i;i=e[i].ne) { int y=e[i].t; if (!link[y]||dfs(link[y],tm)) { link[y]=x; return 1; } } return 0; } void outit() { for (int i=1;i<=num;i++) printf("%d %d\n",e[i].x,e[i].t); } int main() { int n,ans=0; scanf("%d",&n); int tot=0; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) g[i][j]=++tot; for (int i=1;i<=n;i++) scanf("%s",st[i]+1); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { if (st[i][j]=='1') continue; ans++; if ((i&1)^(j&1)) continue; for (int k=0;k<=7;k++) { int x=i+lx[k],y=j+ly[k]; if (x<1||y<1||x>n||y>n||st[x][y]=='1') continue; put(g[i][j],g[x][y]); } } for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { if (st[i][j]=='1') continue; if ((i&1)^(j&1)) continue; if (!link[g[i][j]]) ans-=dfs(g[i][j],g[i][j]); } //outit(); printf("%d\n",ans); return 0; }
相关文章推荐
- 图解javascript this指向什么?
- 远程控制电脑
- Linux Basics command
- java http 请求方法
- .ajax设置成同步的应用场景
- java泛型编程
- linux下apache2两种工作模式及两者切换
- bzoj 3032 七夕祭 | 中位数
- bzoj 2594 水管局长 | LCT | 最小生成树
- bzoj 3706 反色刷 | 一笔画
- bzoj 3108 图的逆变换
- bzoj 2660 最多的方案 | 斐波那契数列
- bzoj 1187 神奇的游乐园 | 插头dp
- bzoj 2173 整数的lqp拆分 | dp | 找规律
- poj 2411| 插头dp
- bzoj 2660 最多的方案 | dp
- bzoj 3170 松鼠聚会 | 旋转坐标
- bzoj 1537 bus|cdq分治
- bzoj 2257 瓶子和燃料
- bzoj 3398 牡牛和牝牛