3175. [TJOI2013]攻击装置【二分图最大独立集】

Description

给定一个01矩阵,其中你可以在0的位置放置攻击装置。每一个攻击装置(x,y)都可以按照“日”字攻击其周围的 8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2),(x+2,y-1),(x-1,y+2),(x-2,y+1), (x+1,y+2),(x+2,y+1)
求在装置互不攻击的情况下,最多可以放置多少个装置。

Input

第一行一个整数N,表示矩阵大小为N*N。接下来N行每一行一个长度N的01串,表示矩阵。

Output

一个整数,表示在装置互不攻击的情况下最多可以放置多少个装置。

Sample Input

3
010
000
100

Sample Output

4

HINT

100%数据 N<=200

数组咋又双叒叕开小了……不过竟然还有90 数据良心(划掉)
第一眼读完题:这咋和炮兵阵地这么像,状压没跑了!
为了验证点击题解:网络流
emmm……我好像傻了这不就是骑士共存么= =……
裸的二分图最大独立集啊QAQ

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<queue>
  6 #define M (1000000+10)
  7 #define N (40000+10)
  8 #define id(x,y) (x-1)*n+y
  9 using namespace std;
 10 struct node
 11 {
 12     int Flow;
 13     int next;
 14     int to;
 15 } edge[M*2];
 16 int Depth[N];
 17 int head[N],num_edge,cnt;
 18 int n,m,s,e,x,y,INF,a[205][205],color[205][205];
 19 int dx[10]= {0,-2,-1,+1,+2,-2,-1,+1,+2};
 20 int dy[10]= {0,-1,-2,-2,-1,+1,+2,+2,+1};
 21 char st[N];
 22 queue<int>q;
 23
 24 void add(int u,int v,int l)
 25 {
 26     edge[++num_edge].to=v;
 27     edge[num_edge].Flow=l;
 28     edge[num_edge].next=head[u];
 29     head[u]=num_edge;
 30 }
 31
 32 bool Bfs(int s,int e)
 33 {
 34     memset(Depth,0,sizeof(Depth));
 35     q.push(s);
 36     Depth[s]=1;
 37     while (!q.empty())
 38     {
 39         int x=q.front();
 40         q.pop();
 41         for (int i=head[x]; i!=0; i=edge[i].next)
 42             if (!Depth[edge[i].to] && edge[i].Flow>0)
 43             {
 44                 Depth[edge[i].to]=Depth[x]+1;
 45                 q.push(edge[i].to);
 46             }
 47     }
 48     return Depth[e];
 49 }
 50
 51 int Dfs(int x,int low)
 52 {
 53     int Min,f=0;
 54     if (x==e || low==0)
 55         return low;
 56     for (int i=head[x]; i!=0; i=edge[i].next)
 57         if (edge[i].Flow>0 && Depth[edge[i].to]==Depth[x]+1 && (Min=Dfs(edge[i].to,min(low,edge[i].Flow))))
 58         {
 59             edge[i].Flow-=Min;
 60             edge[((i-1)^1)+1].Flow+=Min;
 61             low-=Min;
 62             f+=Min;
 63             if (low==0) return f;
 64         }
 65     if (!f) Depth[x]=-1;
 66     return f;
 67 }
 68
 69 int Dinic(int s,int e)
 70 {
 71     int Ans=0;
 72     while (Bfs(s,e))
 73         Ans+=Dfs(s,0x7fffffff);
 74     return Ans;
 75 }
 76
 77 int main()
 78 {
 79     scanf("%d",&n);
 80     s=0,e=200*200+1;
 81     for (int i=1; i<=n; ++i)
 82     {
 83         scanf("%s",st);
 84         for (int j=1; j<=n; ++j)
 85         {
 86             a[i][j]=st[j-1]-‘0‘;
 87             color[i][j]=(i+j)%2;
 88             if (a[i][j]==1) continue;
 89             cnt++;
 90             if (color[i][j]==0) add(s,id(i,j),1), add(id(i,j),s,0);
 91             else add(id(i,j),e,1), add(e,id(i,j),0);
 92         }
 93     }
 94     for (int i=1; i<=n; ++i)
 95         for (int j=1; j<=n; ++j)
 96         {
 97             if (a[i][j]==1 || color[i][j]==1) continue;
 98             for (int k=1; k<=8; ++k)
 99             {
100                 int x=i+dx[k],y=j+dy[k];
101                 if (x<1 || x>n || y<1 || y>n || a[x][y]==1) continue;
102                 add(id(i,j),id(x,y),1);
103                 add(id(x,y),id(i,j),0);
104             }
105         }
106     printf("%d",cnt-Dinic(s,e));
107 }

原文地址:https://www.cnblogs.com/refun/p/8685622.html

时间: 2024-08-28 08:26:38

3175. [TJOI2013]攻击装置【二分图最大独立集】的相关文章

BZOJ 3175 Tjoi2013 攻击装置 二分图最大匹配

题目大意:给定一个n*n的网格图,要在0的位置上放置一些攻击装置,其中一个攻击装置的攻击范围是周围8个"日"字形区域,要求不能互相攻击,求最多放置多少个攻击装置 每两个能互相攻击且能放置的点连一条双向边,然后跑二分图最大点独立集即可 4W个点n^2居然没TLE 是数据太弱还是匈牙利算法太强了? #include<cstdio> #include<cstring> #include<iostream> #include<algorithm>

BZOJ 3175: [Tjoi2013]攻击装置( 匈牙利 )

黑白染成二分图, 然后不能同时选的就连边, 最大匹配数为m, t为不能放的数目, 则题目所求最大点独立集为 n*n-m-t ------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 209; con

[TJOI2013] 攻击装置

3175: [Tjoi2013]攻击装置 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1326  Solved: 636[Submit][Status][Discuss] Description 给定一个01矩阵,其中你可以在0的位置放置攻击装置.每一个攻击装置(x,y)都可以按照"日"字攻击其周围的 8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2),(x+2,y-1),(x-1,y+2),(x-2,y+1), (x

bzoj4808: 马 &amp; bzoj3175: [Tjoi2013]攻击装置 (黑白染色+最小割)

bzoj4808: 马 & bzoj3175: [Tjoi2013]攻击装置 题目:传送门 简要题意: 和n皇后问题差不多,但是这里是每个棋子走日子,而且有些格子不能放棋子.求最多能放多少个棋子. 题解: 双倍经验好评 之前看过机房神犇做...有点印象是最小割. 但是直接割的话不会...要应用到黑白染色: 最开始我想递归染色,也就是取一个开始染,然后递归下去... 波老师说会错ORZ...因为感觉递归的情况不好掌握,有可能会重复染色... 结果有一个肥肠巧妙的方法...直接相邻的染为不同颜色 之

BZOJ3175 [Tjoi2013]攻击装置

Description 给 定一个01矩阵,其中你可以在0的位置放置攻击装置.每一个攻击装置(x,y)都可以按照“日”字攻击其周围的 8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2),(x+2,y-1),(x-1,y+2),(x-2,y+1), (x+1,y+2),(x+2,y+1) 求在装置互不攻击的情况下,最多可以放置多少个装置. Input 第一行一个整数N,表示矩阵大小为N*N.接下来N行每一行一个长度N的01串,表示矩阵. Output 一个整数,表示在装置互不攻击的

BZOJ4808: 马&amp;BZOJ3175: [Tjoi2013]攻击装置

BZOJ3175 Description 给定一个01矩阵,其中你可以在0的位置放置攻击装置.每一个攻击装置(x,y)都可以按照“日”字攻击其周围的 8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2),(x+2,y-1),(x-1,y+2),(x-2,y+1), (x+1,y+2),(x+2,y+1)求在装置互不攻击的情况下,最多可以放置多少个装置. Input 第一行一个整数N,表示矩阵大小为N*N.接下来N行每一行一个长度N的01串,表示矩阵. Output 一个整数,表示在

【bzoj3175】[Tjoi2013]攻击装置

每两个能互相攻击且能放置的点连一条双向边,然后跑二分图最大点独立集即可 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> using namespace std; typedef long long LL; #define M 80010 #define N 210 st

bzoj3175: [Tjoi2013]攻击装置&amp;&amp;4808: 马

终于知道为啥网络流这么受欢迎了. 其实就是构个图模板一下的事儿,比较好打是吧. 然后这题网络流黑白染色(其实感觉上匈牙利更加直接好想啊,但是实际上黑白染色给人感觉就是二分图) st连白而ed连黑,流量为1 不能同时出现的就建无限流量的边 然后sum-最小割 #include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #inc

【最大独立集】BZOJ3175- [Tjoi2013]攻击装置

[题目大意] 给定一个01矩阵,其中你可以在0的位置放置攻击装置.每一个攻击装置(x,y)都可以按照“日”字攻击其周围的 8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2),(x+2,y-1),(x-1,y+2),(x-2,y+1), (x+1,y+2),(x+2,y+1).求在装置互不攻击的情况下,最多可以放置多少个装置. [思路] 最大独立集=总点数-最大二分图匹配 我们都知道最大独立集一般用在二分图里…所以把每个点看作两个点,一个是从它出发,一个是抵达它.实际操作的时候因为