• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jacklee404
Never Stop!
博客园    首页    新随笔    联系   管理    订阅  订阅
估计人数 - 最小路径重复点覆盖

估计人数

题目

估计人数

思路

​ 因为只能向上或者向下走,所以是DAG,求最DAG小路径重复点覆盖我们可以\(O(N_1^3)\)求,其中\(N_1\)为图中\(1\)的数量,因此在允许范围, 难点在于 对于迷宫类型的图,我们求\(Floyd\)的时候,需要先把点提取出来,我们可以给他编号,然后再建图。

Code

#include <bits/stdc++.h>
#define ff first
#define ss second
using i64 = long long;

const int N = 400, M = 400;

typedef std::pair<int, int> PII;

int n, m, cnt;

char a[N][N];

bool st[N];

int h[N], e[M], ne[M], idx;

int id[N][N], d[N][N], match[M];

void add(int a, int b) {
	ne[idx] = h[a], h[a] = idx, e[idx ++] = b;
}

void init() {
	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j <= m; j ++) {
			if (id[i][j]) {
				if (id[i][j + 1]) {
					d[id[i][j]][id[i][j + 1]] = 1;
				}
				if (id[i + 1][j]) {
					d[id[i][j]][id[i + 1][j]] = 1;
				}		
			}
		}	
	}

	for (int k = 1; k <= cnt; k ++) {
		for (int i = 1; i <= cnt; i ++) {
			for (int j = 1; j <= cnt; j ++) {
				d[i][j] |= d[i][k] & d[k][j];
			}
		}	
	}
}

int find(int u) {
	for (int i = 1; i <= cnt; i ++) {
		if (st[i] || !d[u][i]) continue;

		st[i] = true;

		if (!match[i] || find(match[i])) {
			match[i] = u;
			return true;		
		}
  	}
  	return false;
}

int main() {
	std::cin >> n >> m;

	int sum = 0;

	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j <= m; j ++) {
			std::cin >> a[i][j];
			if (a[i][j] == '1') id[i][j] = ++ cnt;
			sum += (a[i][j] == '1');
		}
	}		

	init();

	int res = 0;

	for (int i = 1; i <= cnt; i ++) {
		memset(st, 0, sizeof st);

		if (find(i)) res ++;
	}

	std::cout << sum - res << "\n";
}
posted on 2023-06-08 14:55  Jack404  阅读(10)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3