P8819 [CSP-S 2022] 星战 做题记录
不可以,总司令。
思路
首先,当图中每个点出度为 \(1\) 时,从任一点出发必定会进入环。
证明:假设有一点不符合,则沿着它的出边一直走会到一个出度为 \(0\) 的「终点」,与每个点出度为 \(1\) 矛盾。
想通了这点,这题就不难了。
发现出度要 \(O(n)\) 维护,入度可以 \(O(1)\) 维护,考虑 Hash。
具体地,给每个点赋一个随机权值 \(w(p)\),入度为进入它的点的权值和,则大概率 \(\sum_{p \in V} w(p) = \sum p.\mathrm{in}.\mathrm{wei} \iff \sum p.\mathrm{in}= \lvert V \rvert\)。
Code
#include <iostream>
#include <random>
#define UP(i,s,e) for(auto i=s; i<e; ++i)
#define DOUBLE_HASH 1
using std::cin; using std::cout;
std::mt19937 rdna(0x383494);
using ll = long long;
using ull = unsigned ll;
using i128 = __int128;
constexpr ll MOD1 = 0x383494000111CCF;
constexpr ll MOD2 = 0x383494000222CCF;
constexpr int N = 5e5;
namespace m{ // }{{{
#if DOUBLE_HASH
struct Num{
ll val1, val2;
Num &operator=(Num const&)=default;
Num &operator=(ll x){ val1 = x%MOD1; val2 = x%MOD2; return *this; }
Num(){}
Num(ll x, ll y):val1(x%MOD1), val2(y%MOD2){}
bool operator==(Num const b){
return (val1-b.val1)%MOD1 == 0 && (val2-b.val2)%MOD2 == 0;
}
Num &operator+=(Num const b){
val1 += b.val1;
val1 %= MOD1;
val2 += b.val2;
val2 %= MOD2;
return *this;
}
Num &operator-=(Num const b){
val1 -= b.val1;
val1 %= MOD1;
val2 -= b.val2;
val2 %= MOD2;
return *this;
}
};
#else
using Num = ull;
#endif
Num pri[N], sum[N], allsum[N];
// sum[i]: linked roads, allsum[i]: linked & destroyed
Num nowsum, tot; // all degs; ans when print YES
int in, im;
void work(){
cin >> in >> im;
UP(i, 0, in){
#if DOUBLE_HASH
pri[i] = {(ll)rdna(), (ll)rdna()};
#else
pri[i] = (ll)rdna();
#endif
tot += pri[i];
}
UP(i, 0, im){
int iu, iv;
cin >> iu >> iv; iu--, iv--;
allsum[iv] += pri[iu];
}
UP(i, 0, in){
sum[i] = allsum[i];
nowsum += sum[i];
}
int iq; cin >> iq;
UP(i, 0, iq){
int op, iu, iv;
cin >> op >> iu, iu--;
if(op&1) cin >> iv, iv--;
if(op == 1){
sum[iv] -= pri[iu];
nowsum -= pri[iu];
} else if(op == 2){
nowsum -= sum[iu];
sum[iu] = 0;
} else if(op == 3){
sum[iv] += pri[iu];
nowsum += pri[iu];
} else {
nowsum -= sum[iu];
nowsum += allsum[iu];
sum[iu] = allsum[iu];
}
if(nowsum == tot){
cout << "YES\n";
} else {
cout << "NO\n";
}
}
}
} // {}}}
int main(){std::ios::sync_with_stdio(0); cin.tie(0); m::work(); return 0;}