CSP-S2023T3
引入
星际战火连天际,虫洞据点遭劫难。
修复反击寻时机,连续穿梭定乾坤。
前言
最蚌埠住的一道题,csp-st3紫题30行以内搞定
算是一道半结论题
题目大意
给一个图,有以下四种操作
- 摧毁一条路径
- 摧毁以该点为终点的所有路径
- 修复一条路径
- 修复以该点为终点的所有路径
如果在一次操作后,所有点的出度为1且都能加入一个环内,输出YES,否则NO
题目分析 40pts
其实40分没什么好讲的,超级 $bfs/dfs$ 暴力模拟就可以了,但是由于我在两年前写过,所以决定挂一下
40分代码
为了阅读体验就不在文章内挂了
题目分析 45?60pts
这道题可以说是一个警醒了,从题面可以看出其实满足YES条件是非常苛刻的,如果是随机数据NO情况的概率是极大的,但是在多组数据面前相信大部分人都放弃了骗分的想法
但是在这次csp的比赛重现我发现了这个
? 这是什么奇奇怪怪的部分分做法
结果....
逆天了,ccf数据癫疯之作了
把NO和40分代码结合一下...
幽默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;
}
附上代码,比暴力好写