估计人数

转化为最小可相交路径覆盖问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <cstdio>
#include <vector>
#include <bitset>
#include <functional>
using namespace std;

int n, m, ans, a[21][21], mp[21][21][21][21];
char c;
bitset<404> vis;

int main()
{
scanf("%d%d", &n, &m);
vector<vector<int>> g(n * m + 1);
vector<int> f(n * m + 1, 0);

for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
{
scanf(" %c", &c);
ans += (c - '0');
a[i][j] = c - '0';
if(a[i][j]){
if(a[i-1][j])mp[i-1][j][i][j]=1;
if(a[i][j-1])mp[i][j-1][i][j]=1;
}
}
}

for(int kk=1;kk<=n;++kk){
for(int k=1;k<=m;++k){
for(int ii=1;ii<=n;++ii){
for(int i=1;i<=m;++i){
for(int jj=1;jj<=n;++jj){
for(int j=1;j<=m;++j){
if(ii!=jj&&i!=j){
if(mp[ii][i][kk][k]&&mp[kk][k][jj][j]){
mp[ii][i][jj][j]=1;
}
}
}
}
}
}
}
}

for(int i=1;i<=n;++i){
for(int ii=1;ii<=m;++ii){
for(int j=1;j<=n;++j){
for(int jj=1;jj<=m;++jj){
if(mp[i][ii][j][jj]){
g[(i-1)*m+ii].push_back((j-1)*m+jj);
}
}
}
}
}

function<bool(int)> ck = [&](int x) -> bool
{
for (vector<int>::iterator it = g[x].begin(); it != g[x].end(); ++it)
{
if (!vis[*it])
{
vis[*it] = 1;
if (!f[*it] || ck( f[*it]))
{
f[*it] = x;
return true;
}
}
}
return false;
};
for (int i = 1; i <= n*m; ++i)
{
vis.reset();
if (ck(i))
{
ans -= 1;
}
}

printf("%d", ans);
}