AcWing 379 捉迷藏

AcWing 379 捉迷藏

一、题目描述

Vanicl2 在一片树林里捉迷藏。

这片树林里有 N 座房子,M 条有向道路,组成了一张 有向无环图(DAG)

树林里的树非常茂密,足以遮挡视线,但是沿着道路望去,却是视野开阔。

如果从房子 A 沿着路走下去能够到达 B,那么在 AB 里的人是能够相互望见的。

现在 cl2 要在这 N 座房子里选择 K 座作为藏身点,同时 Vani 也专挑 cl2 作为藏身点的房子进去寻找,为了避免被 Vani 看见,cl2 要求这 K 个藏身点的任意两个之间都没有路径相连。

为了让 Vani 更难找到自己,cl2 想知道最多能选出多少个藏身点。

输入格式
输入数据的第一行是两个整数 NM

接下来 M 行,每行两个整数 x,y,表示一条从 xy 的有向道路。

输出格式
输出一个整数,表示最多能选取的藏身点个数。

数据范围
N200,M30000
输入样例

7 5
1 2
3 2
2 4
4 5
4 6

输出样例:

3

二、解题思路

最小路径覆盖 与 最大独立点集

三、实现代码

#include <bits/stdc++.h>
using namespace std;
const int N = 210, M = 30010;
int n, m;
int g[N][N], st[N];
int match[N];

int dfs(int x) {
    for (int i = 1; i <= n; i++) {
        if (g[x][i] && !st[i]) {
            st[i] = 1;
            int t = match[i];
            if (t == -1 || dfs(t)) {
                match[i] = x;
                return 1;
            }
        }
    }
    return 0;
}

int main() {
    memset(match, -1, sizeof match);
    scanf("%d %d", &n, &m);

    while (m--) {
        int a, b;
        scanf("%d %d", &a, &b);
        g[a][b] = 1;
    }

    // floyd求传递闭包
    for (int k = 1; k <= n; k++)
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                g[i][j] |= g[i][k] & g[k][j];

    int res = 0;
    for (int i = 1; i <= n; i++) {
        memset(st, 0, sizeof st);
        if (dfs(i)) res++;
    }
    printf("%d\n", n - res);
    return 0;
}
posted @   糖豆爸爸  阅读(102)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2020-04-05 MySQL性能测试--分区和分表测试
Live2D
点击右上角即可分享
微信分享提示