【P8819 [CSP-S 2022]】 星战 题解(图论 + 哈希)
图论 + 哈希。
因为实在是太妙了所以写个题解。
Solution
-
因为每个点的出度都为
,所以从任意一点出发永远可以走下去,故每次只需判断每个点度数是否为 即可。 -
然后一三操作显然直接
维护, 。 -
考虑二四操作。每次操作显然对点
的出度没有影响,但是对边的起点 的出度有影响。考虑如何把操作转化到对 的修改上来。 -
发现可以维护一个点的入度。如果不考虑反攻时刻的判断,四个操作在入度上的修改都能做到
。 -
根据入度 = 出度,反攻时刻的判断可以变为所有节点的入度值等于
。但是这样无法保证每个节点的出度都是 。 -
考虑优化一下入度的计算,实现
判断所有节点的出度一定都为 。结合起来考虑,发现如果使用哈希的思想,给每个节点随机权值 ,定义一个节点的入度为所有边起点的权值和,那么如果 ,则能保证每个节点都有一条出边指向某个节点。 -
解题重点在于转化与哈希思想。如果想到第一条和哈希,此题基本迎刃而解。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for(int i = a; i <= b; ++i)
const int maxn = 5e5 + 5;
int n, m, q;
int tot, r[maxn], w[maxn], g[maxn];
mt19937 rng(time(0));
signed main(){
scanf("%lld%lld", &n, &m);
rep(i, 1, n) w[i] = rng(), tot += w[i];
int rec = 0;
while(m--){ int u, v; scanf("%lld%lld", &u, &v);
g[v] = (r[v] += w[u]), rec += w[u];
}
scanf("%lld", &q);
while(q--){
int t; scanf("%lld", &t);
if(t == 1){ int u, v; scanf("%lld%lld", &u, &v);
r[v] -= w[u], rec -= w[u];
} else if(t == 2){ int v; scanf("%lld", &v);
rec -= r[v], r[v] = 0;
} else if(t == 3){ int u, v; scanf("%lld%lld", &u, &v);
r[v] += w[u], rec += w[u];
} else{ int v; scanf("%lld", &v);
rec += g[v] - r[v], r[v] = g[v];
} if(rec == tot) printf("YES\n"); else printf("NO\n");
}
return 0;
}
Thanks for reading.
标签:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效