CF1322C - Instant Noodles
题意
给一个 个点的二分图,左右两遍各 个点,现在给出右边每个点的权值 ,以及 条连接左右两边的边。左边选取一个非空集合 ,与之有边相连的右边的点集为 , 中点权值和为 ,现在求所有可能的 的 值
题解
记
,
为
整除
,且
=>
现在考虑集合
①
和
无交集
=>
=>
②
和
有交集
=>
=>
所以其实所有
都可以用各个不一样的
相加得到
即右边的点只会对应一个集合,那么我们从右边的点来确定左边的集合即可
最后答案就是
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX = 5e5 + 10;
int T, N, M;
ll val[MAX];
set<int> g[MAX];
map<set<int>, ll> mp;
//集合的映射,这里hash也能做
//这样最后mp里面的值就是所有的f(S[i])了
int main() {
scanf("%d", &T);
while (T--) {
mp.clear();
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; i++) scanf("%lld", &val[i]), g[i].clear();
while (M--) {
int u, v; scanf("%d%d", &u, &v);
g[v].insert(u);//右边的点确定的集合, 用g[v]来表示
}
for (int v = 1; v <= N; v++)
if (!g[v].empty())
mp[g[v]] += val[v];//找对应的集合
ll ans = 0;//全是0那答案就是0
for (auto &i: mp) ans = ans ? __gcd(ans, i.second) : i.second;
printf("%lld\n", ans);
}
return 0;
}