CF1322C Instant Noodles
CF1322C Instant Noodles - 洛谷
题面比较绕,看了题解的离谱结论:求所有点集权值和的 \(gcd\) 等价于把所有连边相同的右侧点合并之后求权值的 \(gcd\)。
现在考虑怎么合并两个连边相同的右侧点。这边要积累经验,可以直接把集合放在 \(map\) 的 \(key\) 上,将权值和作为 \(value\),然后就可以愉快地合并了。
时间复杂度 \(O(nlogn)\)。
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l); i <= (r); ++ i)
#define G(i,r,l) for(int i(r); i >= (l); -- i)
#define int ll
using namespace std;
using ll = long long;
const int N = 1e6 + 10;
int ans, T, n, m, c[N];
set<int> e[N];
map<set<int>, int> mp;
void solve(){
cin >> n >> m;
F(i, 1, n) cin >> c[i];
F(i, 1, m){
int u, v;
cin >> u >> v;
e[v].insert(u);
}
F(i, 1, n) if(e[i].size()) mp[e[i]] += c[i];
for(auto x : mp) ans = __gcd(ans, x.second);
cout << ans << '\n';
ans = 0;
map<set<int>, int>().swap(mp);
F(i, 1, n) set<int>().swap(e[i]);
}
signed main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> T;
while(T --) solve();
return fflush(0), 0;
}

浙公网安备 33010602011771号