Codeforces Round #805 (Div. 3)

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值