CSP-S2023T3

引入

星际战火连天际,虫洞据点遭劫难。

修复反击寻时机,连续穿梭定乾坤。

前言

最蚌埠住的一道题,csp-st3紫题30行以内搞定
算是一道半结论题

题目大意

给一个图,有以下四种操作

  1. 摧毁一条路径
  2. 摧毁以该点为终点的所有路径
  3. 修复一条路径
  4. 修复以该点为终点的所有路径

如果在一次操作后,所有点的出度为1且都能加入一个环内,输出YES,否则NO

题目分析 40pts

其实40分没什么好讲的,超级 $bfs/dfs$ 暴力模拟就可以了,但是由于我在两年前写过,所以决定挂一下
40分代码
为了阅读体验就不在文章内挂了

题目分析 45?60pts

这道题可以说是一个警醒了,从题面可以看出其实满足YES条件是非常苛刻的,如果是随机数据NO情况的概率是极大的,但是在多组数据面前相信大部分人都放弃了骗分的想法
但是在这次csp的比赛重现我发现了这个
1
这是什么奇奇怪怪的部分分做法
结果....
2
逆天了,ccf数据癫疯之作了
把NO和40分代码结合一下...
3
幽默60分

题目分析 100pts

其实不难发现,如果所有点满足出度为1的话,那么所有点肯定是构成一个环的
但是维护判断出度的常规做法也是超时的,我们可以反过来想,如果所有点出度和为 num 的话,那么所有点的入度和也一定为num
显然在本题内入度是相当好维护的,四种操作无非是加一、减一、清零与恢复,我们给每个点赋值一个随机权,运用类似哈希的思想避免判重,只要所有点的入度和刚好是点权和那么就满足了出度全部为1的情况

#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
int n,m,q,a[N];
long long to[N],sum[N],tot,ans;
int main(){
	mt19937 rnd(time(0));
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		ans+=(a[i] = rnd());
	for(int i=1,u,v;i<=m;++i)
		scanf("%d%d",&u,&v),to[v]+=a[u],sum[v]=to[v],tot+=a[u];
	scanf("%d",&q);
	for(int i=1,t,u,v;i<=q;++i){
		scanf("%d%d",&t,&u);
		if(t==1)
		scanf("%d",&v),to[v]-=a[u],tot-=a[u];
		if(t==2)
		tot-=to[u],to[u]=0;
		if(t==3)
		scanf("%d",&v),to[v] += a[u],tot+=a[u];
		if(t==4)
		tot += sum[u]-to[u],to[u]=sum[u];
		puts(tot==ans?"YES":"NO");
	}
	return 0;
}

附上代码,比暴力好写

posted @ 2024-10-21 16:34  健康铀  阅读(10)  评论(0编辑  收藏  举报