专栏文章

题解:P10938 Vani和Cl2捉迷藏

P10938题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miq7f6j1
此快照首次捕获于
2025/12/04 00:11
3 个月前
此快照最后确认于
2025/12/04 00:11
3 个月前
查看原文

题意

最小可交路径点覆盖。

前置知识

最小无交路径点覆盖。
令最小无交路径点覆盖数为 xx,二分图最大匹配数为 yy,图总点数为 nn
结论是:x=nyx = n - y

思路

考虑转化。如果一个点可以间接到达另一个点,那么在图上建一条直接连接两点的边,做最小无交路径点覆盖就相当于原先的最小可交路径点覆盖。
这个证明是很好想的,可以自行思考。
对于判断一个点是否可以间接到达另一个点,用 Floyd 做传递闭包即可。
代码:
CPP
#include <bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;

const int N = 205;
int n, m, u, v, mch[N], dis[N][N];
bool vis[N];
vector<int> g[N];

inline bool dfs(int x) {
	for(auto u : g[x])
		if(! vis[u]) {
			vis[u] = true;
			
			if(! mch[u] || dfs(mch[u])) {
				mch[u] = x;
				
				return true;
			}
		}
	
	return false;
}

signed main() {
	ios_base :: sync_with_stdio(NULL);
	cin.tie(nullptr);
	cout.tie(nullptr);
	
	cin >> n >> m;
	for(int i = 1 ; i <= m ; ++ i) {
		cin >> u >> v;
		
		dis[u][v] = true;
	}
	
	for(int k = 1 ; k <= n ; ++ k)
		for(int i = 1 ; i <= n ; ++ i)
			for(int j = 1 ; j <= n ; ++ j)
				dis[i][j] |= (dis[i][k] & dis[k][j]);
	
	for(int i = 1 ; i <= n ; ++ i)
		for(int j = 1 ; j <= n ; ++ j)
			if(dis[i][j]) g[i].pb(j);
	
	int ans = 0;
	
	for(int i = 1 ; i <= n ; ++ i) {
		memset(vis, false, sizeof vis);
		
		if(dfs(i)) ++ ans;
	}
	
	cout << n - ans;
	
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...