您的位置:首页 > 其它

计蒜客习题-城市规划 最小边覆盖集

2018-03-22 22:16 435 查看
不用管独立的居民区,统计点数的时候加进来就行了

由于是无向图 要插双向边

//最小边覆盖集==最大点独立集==顶点数-最大匹配
//把地图交替染色 构建二分图
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
#define p1 (i-1)*m+j-1
#define p2 (i-2)*m+j
#define N n*m
inline int read() { char c = getchar(); int s = 0, f = 1; while (c<'0' || c>'9') { if (c == '-') f = -1; c = getchar(); }while (c >= '0'&&c <= '9') { s = s * 10 + c - 48; c = getchar(); }return s*f; }
int g[107][107], ans[10007], node[107][107], cnt = 0, n, m;
vector<int> g2[10001];
bool vis[10007];
bool dfs(int u) {
for (int i = 0; i <g2[u].size(); i++) {
int v=g2[u][i];
if (!vis[v]) {      //有边
vis[v] = true;
if (ans[v] == -1 || dfs(ans[v])) {
ans[v] = u;
return true;
}
}
}
return false;
}
int hungary() {
int res = 0;
memset(ans, -1, sizeof(ans));
for (int i = 1; i <= cnt; i++) {
memset(vis, false, sizeof(vis));
res += dfs(i);
}
return res;
}
int main() {
n = read(); m = read();
char c = getchar();
for (int i = 1, j = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++) {
while (c != 'o'&&c != '*') {
c = getchar();
}
if (c == '*') {
node[i][j] = ++cnt;
if (g[i - 1][j] == 1){
g2[node[i][j]].push_back(node[i - 1][j]);
g2[node[i - 1][j]].push_back(node[i][j]);
}
if (g[i][j - 1] == 1) {
g2[node[i][j]].push_back(node[i][j - 1]);
g2[node[i][j - 1]].push_back(node[i][j]);
}
}
g[i][j] = c == '*' ? 1 : 0;
c = getchar();
}
}
printf("%d", (cnt * 2 - hungary()) >> 1);
//getchar();

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息