E
找奇环
法一:并查集维护连通块
int tag[N], rec[N];
int fa[N], bjnum[N];
int find(int a) {
if (a == fa[a]) return a;
fa[a] = find(fa[a]);
bjnum[fa[a]] += bjnum[a];
bjnum[a] = 0;
return fa[a];
}
void union_set(int a, int b) {
a = find(a);
b = find(b);
if (a == b) return;
bjnum[b] += bjnum[a];
bjnum[a] = 0;
fa[a] = b;
}
signed main() {
cf {
n = read();
rep(i, 1, n) tag[i] = 0, fa[i] = i, bjnum[i] = 1, rec[i] = 0;
bool flag = 0;
rep(i, 1, n) {
a = read();
b = read();
rec[a]++;
rec[b]++;
if (a == b) flag = 1; //不行
if (!tag[a])
tag[a] = i;
else { union_set(i, tag[a]); }
if (!tag[b])
tag[b] = i;
else { union_set(i, tag[b]); }
}
if (!flag) {
rep(i, 1, n) {
if (bjnum[i]) {
int y = find(i);
if (y != i) {
bjnum[find(i)] += bjnum[i];
bjnum[i] = 0;
}
}
}
rep(i, 1, n) {
// cout << bjnum[i] << " ";
if (bjnum[i] & 1) {
flag = 1;
break;
}
}
}
rep(i, 1, n) {
if (rec[i] != 2) {
flag = 1;
break;
}
}
if (flag)
cout << "NO\n";
else
cout << "YES\n";
}
return 0;
}
法二:二分图染色
int tag[N], col[N];
bool flag = 0;
vector<int> v[N];
void dfs(int x, int cl) {
col[x] = cl;
for (auto y : v[x]) {
if (!col[y])
dfs(y, 3 - cl);
else if (col[y] == cl)
flag = 1;
}
}
int rec[N];
signed main() {
cf {
n = read();
rep(i, 1, n) tag[i] = 0, col[i] = 0, v[i].clear(), rec[i] = 0;
flag = 0;
rep(i, 1, n) {
a = read();
b = read();
rec[a]++;
rec[b]++;
if (a == b) flag = 1; //不行
if (!tag[a])
tag[a] = i;
else
v[i].push_back(tag[a]), v[tag[a]].push_back(i);
if (!tag[b])
tag[b] = i;
else
v[i].push_back(tag[b]), v[tag[b]].push_back(i);
}
if (flag) {
cout << "NO\n";
continue;
}
rep(i, 1, n) {
if (!col[i]) dfs(i, 1);
}
rep(i, 1, n) {
if (rec[i] != 2) {
flag = 1;
break;
}
}
if (flag)
cout << "NO\n";
else
cout << "YES\n";
}
return 0;
}
F
2可以×/÷任意个数
不妨除完所有的2 对剩余的部分进行匹配
map<int, int> p1;
signed main() {
cf {
bool flag = 0;
p1.clear();
n = read();
rep(i, 1, n) {
a = read();
while (a % 2 == 0) {
a /= 2;
}
p1[a]++;
} // a的因子
rep(i, 1, n) {
a = read();
while (a % 2 == 0) {
a /= 2;
}
if (!p1[a]) {
while (a) {
a /= 2;
if (p1[a]) {
p1[a]--;
break;
}
}
if (a == 0) { flag = 1; }
} else
p1[a]--;
}
if (flag)
cout << "NO\n";
else
cout << "YES\n";
}
return 0;
}
G
可以参考Codeforces Round #805 (Div. 3) E(染色) F(贪心) G(lca) - 知乎讲的很清楚
注意直链不需要额外判断 ed==0就是直链了
bool cmp(int a, int b) {
return dpth[a] < dpth[b];
}
vector<int> pp;
signed main() {
n = read();
rep(i, 2, n) {
a = read();
b = read();
v[a].push_back(b);
v[b].push_back(a);
}
Q = read();
t = log(n) / log(2) + 1;
bfs();
rep(tt, 1, Q) {
m = read();
rep(i, 1, m) {
u[i] = read();
}
if (m <= 2) {
YES;
continue;
}
sort(u + 1, u + 1 + m, cmp);
int st = u[m], ed = 0;
// pp.clear();
per(i, m - 1, 1) {
if (lca(st, u[i]) != u[i]) {
ed = u[i];
break;
}
}
if (ed == 0) {
YES;
continue;
}
int now = lca(ed, st);
bool flag = 0;
rep(i, 1, m) {
if (lca(u[i], st) == u[i] && lca(u[i], ed) == now) {
} else if (lca(u[i], st) == now && lca(u[i], ed) == u[i]) {
} else {
flag = 1;
break;
}
}
if (flag)
NO;
else
YES;
}
return 0;
}