欢迎大家到我的博客,观感更佳
标题传送门:P8819 [CSP-S 2022] 星战
目录
-
前置知识
-
题目描述
-
解题思路
-
CODE
前置知识
- 度数、入度、出度
基础概念:在有向图中,箭头是具有方向的,从一个顶点指向另一个顶点,这样一来,每个顶点被指向的箭头个数,就是它的入度。从这个顶点指出去的箭头个数,就是它的出度
参考文章:什么是出度入度?
- 梅森旋转算法( M e r s e n n e t w i s t e r Mersenne twister Mersennetwister)
基础概念:梅森旋转算法( M e r s e n n e t w i s t e r Mersenne twister Mersennetwister)是一个伪随机数发生算法。由松本真和西村拓士在1997年开发,基于有限二进制字段上的矩阵线性递归。可以快速产生高质量的伪随机数,修正了古典随机数发生算法的很多缺陷。
参考文章:MT19937(梅森旋转算法)
题目描述
在一张有向图上,实现四种操作:
一、失活某条边
二、激活某条边
三、失活以某个点为结束节点的所有边
四、激活以某个点为结束节点的所有边
每次操作后若图上所有点的出度为1并且可以走到一个环上,输出YES,否则输出NO。
解题思路
S t e p Step Step O n e One One
首先,如果每个点的出度都为1,那么就有每个点都能走到另一个点,而另一个点的出度也为1,那么另一个点就能走到再另一个点。所以从任意点开始行走,皆可保证每次都有下一个点可以走,即一定会走到一个环上。
因此,条件“每次操作后若图上所有点的出度为1并且可以走到一个环上”在满足所有点出度为1时即可满足,后半句是无用的。
S t e p Step Step T w o Two Two
因此,对于一个符合条件的图,出度之和等于点数 n n n。又因为不需要检查环的条件,所以,只要能实时维护出度的值,就能切掉本题。
那么,大功告成!(你想多了)
说明:由于不好叙述,下面将一条有向边解剖为父节点,边,子节点
对于本题的“激活某边和失活某边”的操作,只需要 O ( 1 ) O(1) O(1)的复杂度,将父节点的出度加1或减1即可。
那么对于“激活或失活以某个点为结束节点的所有边”该怎么办呢?找这个点的子节点,将其出度加1或减1。到这,我们就需要有一个图的存储,才能完成如上操作,而且还需要特判特殊情况:待激活或失活的点有已激活或失活的子节点,这样就会重复导致错误。
就算我们把这些都处理干净了,但是发现对于激活或失活以某个点为结束节点的所有边的操作,需要 O ( n ) O(n) O(n)的复杂度,是及为不优的。
因此,40分CODE诞生:
#include<bits/stdc++.h>
using namespace std;
int CD[500005];
vector<int> M[500005];
vector<pair<int,bool> > book[500005];
bool find(vector<pair<int,bool> > V,int u,bool Point){