P4304 [TJOI2013]攻击装置 网络流

Posted orangeko

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4304 [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)

求在装置互不攻击的情况下,最多可以放置多少个装置。

输入格式

第一行一个整数N,表示矩阵大小为N*N。

接下来N行每一行一个长度N的01串,表示矩阵。

输出格式

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

输入输出样例

输入 #1
3
010
000
100
输出 #1
4

说明/提示

30%数据N<=50

100%数据 N<=200

 

思路

  方格取数问题加强版、骑士共存问题的魔改

  做过任意一个就可以秒了

 

CODE

 

技术图片
  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 
  6 
  7 const int maxn = 1e6 + 7;
  8 
  9 const int inf = 0x3f3f3f3f;
 10 
 11 
 12 
 13 template<class T>inline void read(T &res)
 14 
 15 {
 16 
 17     char c;T flag=1;
 18 
 19     while((c=getchar())<0||c>9)if(c==-)flag=-1;res=c-0;
 20 
 21     while((c=getchar())>=0&&c<=9)res=res*10+c-0;res*=flag;
 22 
 23 }
 24 
 25 
 26 
 27 struct edge{int from,to,cap,flow;};
 28 
 29 int s, t, n, m;
 30 
 31 struct isap
 32 
 33 {
 34 
 35     int n,s,t,p[maxn],d[maxn],cur[maxn],num[maxn];
 36 
 37     bool vis[maxn];
 38 
 39     vector<int>g[maxn];
 40 
 41     vector<edge>edges;
 42 
 43     void init(int n,int s,int t) {
 44 
 45         this->n = n;
 46 
 47         this->s = s;
 48 
 49         this->t = t;
 50 
 51         for(int i = 1;i <= n;i++) g[i].clear();
 52 
 53         edges.clear();
 54 
 55     }
 56 
 57     void addegde(int from,int to,int cap) {
 58 
 59         edges.push_back((edge){from, to, cap, 0});
 60 
 61         edges.push_back((edge){to, from, 0, 0});
 62 
 63         int m = edges.size();
 64 
 65         g[from].push_back(m-2);
 66 
 67         g[to].push_back(m-1);
 68 
 69     }
 70 
 71 
 72 
 73     int augment() {///找增广路
 74 
 75         int x = t,a = inf;
 76 
 77         while(x!=s) {
 78 
 79             a = min(a, edges[p[x]].cap - edges[p[x]].flow);
 80 
 81             x = edges[p[x]].from;
 82 
 83         }
 84 
 85         x=t;
 86 
 87         while(x != s) {
 88 
 89             edges[p[x]].flow += a;
 90 
 91             edges[p[x]^1].flow = -a;
 92 
 93             x = edges[p[x]].from;
 94 
 95         }
 96 
 97         return a;
 98 
 99     }
100 
101     int maxflow() {///更新最大流
102 
103         int flow = 0;
104 
105         memset(num, 0, sizeof(num));
106 
107         memset(cur, 0, sizeof(cur));
108 
109         for(int i = 1; i <= n; i++) num[d[i]]++;
110 
111         int x = s;
112 
113         while(d[s] < n) {///最长的一条链上,最大的下标是nv-1,如果大于等于nv说明已断层
114 
115             if(x == t) {
116 
117                 flow += augment();
118 
119                 x = s;//回退
120 
121             }
122 
123             bool ok = 0;
124 
125             for(int i = cur[x]; i < g[x].size(); i++) {
126 
127                 edge &e = edges[g[x][i]];
128 
129                 if(d[x] == d[e.to] + 1 && e.cap > e.flow) {
130 
131                     p[e.to] = g[x][i];
132 
133                     cur[x] = i;x = e.to;
134 
135                     ok = 1;
136 
137                     break;
138 
139                 }
140 
141             }
142 
143             if(!ok) {
144 
145                 int m = n-1;
146 
147                 for(int i = 0; i < g[x].size();i++) {
148 
149                     edge &e=edges[g[x][i]];
150 
151                     if(e.cap>e.flow) m=min(m,d[e.to]);
152 
153                 }
154 
155                 num[d[x]]--;
156 
157                 if(!num[d[x]]) break;
158 
159                 d[x] = m+1;
160 
161                 num[d[x]]++;
162 
163                 cur[x] = 0;
164 
165                 if(x != s) x = edges[p[x]].from;
166 
167             }
168 
169         }
170 
171         return flow;
172 
173     }
174 
175 }ISAP;
176 
177 inline int id(int x, int y) {
178     return (x-1) * n + y;
179 }
180 
181 char a[507][507];
182 
183 int dr[8] = {-2, -2, -1, -1, 1, 1, 2, 2};
184 int dc[8] = {1, -1, 2, -2, 2, -2, 1, -1};
185 
186 int main()
187 {
188     read(n);
189     
190     memset(a, 0, sizeof(a));
191     s = 0, t = n * n + 1;
192     ISAP.init(n * n * 2, s, t);
193     for ( int i = 1; i <= n; ++i ) {
194         for ( int j = 1; j <= n; ++j ) {
195             cin >> a[i][j];
196             if(a[i][j] == 1)
197                 ++m;
198         }
199     }
200     // for ( int i = 1; i <= n; ++i ) {
201     //     for ( int j = 1; j <= n; ++j ) {
202     //         cout << a[i][j];
203     //     }
204     //     cout << endl;
205     // }
206     for ( int i = 1; i <= n; ++i ) {
207         for ( int j = 1; j <= n; ++j ) {
208             if(a[i][j] == 1)
209                 continue;
210             if((i + j) & 1) {
211                 ISAP.addegde(s, id(i, j), 1);
212                 for ( int k = 0; k <= 7; ++k ) {
213                     int x = i + dr[k], y = j + dc[k];
214                     if(x < 1 || x > n || y < 1 || y > n) {
215                         continue;
216                     }
217                     ISAP.addegde(id(i, j), id(x, y), 1);
218                 }
219             }
220             else {
221                 ISAP.addegde(id(i, j), t, 1);
222             }
223         }
224     }
225     int maxflow = ISAP.maxflow();
226     //dbg(maxflow);
227     int ans = n * n - m - maxflow;
228     cout << ans << endl;
229     return 0;
230 }
View Code

 

 

 

以上是关于P4304 [TJOI2013]攻击装置 网络流的主要内容,如果未能解决你的问题,请参考以下文章

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

[TJOI2013] 攻击装置

[Tjoi2013]攻击装置

[TJOI2013]攻击装置

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

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