【JZOJ】3423. Vani和Cl2捉迷藏

2023-11-22 10:59
文章标签 jzoj cl2 捉迷藏 3423 vani

本文主要是介绍【JZOJ】3423. Vani和Cl2捉迷藏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

Time Limits: 1000 ms Memory Limits: 262144 KB
vani和cl2在一片树林里捉迷藏……

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

树林里的树非常茂密,足以遮挡视线,但是沿着道路望去,却是视野开阔。如果从房子A沿着路走下去能够到达B,那么在A和B里的人是能够相互望见的。

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

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

Input

第一行两个整数N,M。

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

Output

一个整数K,表示最多能选取的藏身点个数。

Sample Input

4 4

1 2

3 2

3 4

4 2

Sample Output

2

Data Constraint

对于20% 的数据,N≤10,M<=20。

对于60% 的数据, N≤100,M<=1000。

对于100% 的数据,N≤200,M<=30000,1<=x,y<=N。

思路

初读题,没啥思路,以为是图论瞎搞题,开始回想学过的各种图论知识。

(几个小时过去了。。。。)

引入最小链覆盖:

从有向无环图(DAG)中选出若干点不相交的链,使得这些链覆盖所有的点,并且链的条数最小。链的定义是一条连续路径,并且不经过重复的点。

设没有用到的边是黑色边,用到的边是彩色边。那么一条彩色边对应一个连出去的点。由于链的个数是没有连出去的点的数量,因此我们只需要最大化彩色边个数a。答案即是n-a。

建立两个n个点的点集X和Y,如果原图中存在一条边A->B,就在X中的A向Y中的B连边,跑最大匹配就能找到最大彩色边个数。这是对的,是因为X中对应的是只有一条边连出去,而Y对应的是只有一条边连过来。因此一个点最多连进去一次,连出去一次。

以上已经很详尽的描述了非重(即不相交的情况下)的最小链覆盖的如何做。
感谢pechpo大佬。

很明显这道题就是在最小链覆盖的情况下,在每条链上任挂一个点。

但是,仅仅做非重的情况是不行的,考虑如下图例子:

在上图中,非重最小链覆盖的一种最优解为:

1:1->3->4->6;
2:2;
3:5;

然而,可重最小链覆盖的一种最优解为:

1:1->3->4->6
2:2->3->4->5

即问题转化为将非重最小链覆盖变为可重最小链覆盖。
考虑N很小(N<=200),且无环,可以预处理出各个点的联通关系。
对于两个点i,j。若i能走到j,则在二分图中X部i连向Y部j。
如下图,黑边为直接相连边,红边为间接向连边。
第一个图为处理非重最小链覆盖的二分图,第二个图为可重。


这样建图后,对于每个点,它能走到的点在它被选后,都不能选了(十分简明)。

代码

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=205;
int N,M,cnt,Ans,t[MAXN][MAXN];
int vis[MAXN*2],match[MAXN*2];
vector<int>P[MAXN];
int dfs(int u){int size=P[u].size();cnt++;for(int i=0;i<size;i++){int v=P[u][i];if(vis[v])continue;vis[v]=1;dfs(v);for(int j=1;j<=N;j++)t[u][j]=max(t[u][j],t[v][j]);}
}
void Init(){for(int i=1;i<=N;i++){int size=P[i].size();for(int j=0;j<size;j++)t[i][P[i][j]]=1;}while(cnt!=N){int Root=0;for(int i=1;i<=N;i++)if(!vis[i]){Root=i;break;}vis[Root]=1;dfs(Root);}for(int i=1;i<=N;i++)P[i].clear();for(int i=1;i<=N;i++)for(int j=1;j<=N;j++)if(t[i][j])P[i].push_back(j+N);memset(vis,0,sizeof(vis));
}
int Dfs(int u){int size=P[u].size();for(int i=0;i<size;i++){int v=P[u][i];if(vis[v])continue;vis[v]=1;if(match[v]==-1||Dfs(match[v])){match[v]=u;match[u]=v;return 1;}}return 0;
}
int main(){scanf("%d%d",&N,&M);for(int i=1,x,y;i<=M;i++){scanf("%d%d",&x,&y);P[x].push_back(y);}Init();memset(match,-1,sizeof(match));for(int i=1;i<=N;i++){memset(vis,0,sizeof(vis));Ans+=Dfs(i);}printf("%d\n",N-Ans);
}

这篇关于【JZOJ】3423. Vani和Cl2捉迷藏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/409673

相关文章

Jzoj 条件循环(while,do while) 部分代码(共25题)

1020: 【入门】编程求1+3+5+...+n #include <bits/stdc++.h>using namespace std;int n, sum;int main() {scanf("%d", &n);for(int i=1; i<=n; i+=2){sum+=i;} printf("%d", sum);return 0;} 1012: 【入门】两数比大小 #i

Jzoj 二维数组部分代码(共13题)

2788: 【入门】二维数组的输入输出 边输入边输出 #include <bits/stdc++.h>using namespace std;int n, m, a[11][11];int main(){scanf("%d %d", &n, &m);//边输入边输出for(int i=1; i<=n; ++i){for(int j=1; j<=m; ++j){scanf("%d", &

1个人躲,5个人抓!《极限竞速:地平线5》全新游戏模式“捉迷藏”即将推出

风靡全球的赛车竞速游戏《极限竞速:地平线5》即将推出全新游戏模式——捉迷藏(Hide & Seek)。 《极限竞速:地平线5》日前发布了全新预告,展示了即将于 9 月 10 日推出的捉迷藏模式游戏玩法。该预告是日前举办的2024 年科隆国际游戏展 Xbox 展会直播上的收支宣传片。预告证实捉迷藏模式为5 vs 1 玩法,负责藏得玩家只有1 名,必须在 5 名寻找者抓住他之前冲过终点线。  在

还每天都能在一片片金黄色的麦地里捉迷藏

里面有戚老师的吃饭 今天的里面有戚老师的吃饭,又出去拿了一块抹布,收卷我们说,还每天都能在一片片金黄色的麦地里捉迷藏,天哪,我用锅铲不停的搅动着,我们还没写完,万老师就把试卷改完了,看看手中拿的吃饭是什么,望着她那忙碌的背影。 什么也没看见,我想起落了什么,两只皮靴有型地挺着,而在我需要帮助时,其余0分,然后,也不行,鸡蛋终于准时下锅了,帮助我。 我急急忙忙的吃饭从冰箱里拿了一个蛋,就这样

括号序列 || 动态树分治 bzoj1095【ZJOI2007】Hide 捉迷藏

题目大意: 给出一棵树,初始全是黑点,每次修改把黑点变成白点或把白点变成黑点,每次查询树中黑点最远距离。 题目分析: 两种做法。 第一种:括号序列 这个做法真的比较神啊,无论是代码长度,时间,还是空间都完虐动态树分治。 上边的是动态树分治,下边的是括号序列。 做法大致是把树转化成一个括号序列,然后维护一个线段树。 对于这个神做法,我还是不多BB,大家一起膜岛娘吧 _ (:зゝ∠

jzoj 5770 可爱精灵宝贝

题目 题解 –是区间dp(好像dfs加神秘玄学剪枝也能过?) 首先,我们可以发现这个人走过的位置是一个区域,而且区域内部的精灵要么被抓,要么消失了(总之就是与以后的转移没有关系) 所以,状态定义: f[l][r][t] :当这个人走过区间[l,r],且目前在l处,时间为t时的最大分值 注意,l,r的左右位置要根据大小自己判断 然后我们又发现,现在这个人只有两种方法:左走或右走

[离散化][区间DP]JZOJ 5770 可爱精灵宝贝

日常黑Pokeman Go Description Branimirko是一个对可爱精灵宝贝十分痴迷的玩家。最近,他闲得没事组织了一场捉精灵的游戏。游戏在一条街道上举行,街道上一侧有一排房子,从左到右房子标号由1到n。 刚开始玩家在k号房子前。有m个精灵,第i只精灵在第A[i]栋房子前,分值是B[i],以及它在T[i]秒内(含)存在,之后消失。Branimirko可以选择移动至相邻的房子,耗时

[权值线段树]JZOJ 3236 矮人排队

Description 在七山七海之外的一个小村庄,白雪公主与N个矮人住在一起,所有时间都花在吃和玩League of Legend游戏。白雪公主决心终结这样的生活,所以为他们举办了体育课。 在每节课开始时,矮人必须按他们的身高站队。假定矮人们有高度1,2,...,N(每个人高度互不相同)。然而,由于不健康的生活方式,矮人的智力有所恶化,所以他们没有能力依照自己的高度排序。 因此,白雪公主发

JZOJ 1495. 宝石(附加扫描线讲解)

JZOJ 1495. 宝石 题目大意:给你N个 ( K + 1 ) × ( K + 1 ) (K+1)\times(K+1) (K+1)×(K+1)的正方形以及他们左上角的那个顶点的坐标和它的权值,求最大的覆盖的权值。 这一题可以用二维前缀和做,但是无法拿到满分。 满分做法:扫描线。 假如现在有这么两个长方形,权值都为1(不要问为什么是长方形,这里只是为了方便讲解而已),它们摆放如图: 首

【JZOJ A组】 大逃杀

Description 自从 Y 君退役之后,她就迷上了吃鸡,于是她决定出一道吃鸡的题。 Y 君将地图上的所有地点标号为 1 到 n,地图中有 n − 1 条双向道路连接这些点,通过一条 双向道路需要一定时间,保证从任意一个点可以通过道路到达地图上的所有点。 有些点上可能有资源,Y 君到达一个有资源的点后,可以选择获取资源来使自己的武力值增 加 wi,也可以选择不获取资源。如果 Y 君获取了