Hướng dẫn giải của Bedao Regular Contest 08 - KINGDOM


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Tác giả: bedao

Biết rằng đồ thị đã cho là một cây. Vì thế, ta nhận thấy điều kiện với đỉnh ~i~ bị chiếm đóng, trong ~n-1~ đỉnh còn lại, những đỉnh có thể đến được với nhau phải có cùng chỉ số chiến thuật, đồng nghĩa với việc khi bỏ đi đỉnh ~i~, những đỉnh thuộc cùng một thành phần liên thông (đến được nhau) phải có cùng chỉ số chiến thuật.

Điều trên đồng nghĩa với việc nếu ~i~ là một đỉnh thỏa mãn, thì sau khi bỏ đỉnh ~i~ (cùng các cạnh nối với ~i~), tất cả các cạnh còn lại đều là cạnh nối ~2~ đỉnh có cùng chỉ số chiến thuật.

Gọi ~tot~ là tổng số lượng cạnh ~i-j~ mà ~c_i \neq c_j~ trong ~n-1~ cạnh đã cho.

Gọi ~cnt_u~ là số lượng cạnh ~u-v~ mà ~c_u \neq c_v~.

Khi đó nếu ~tot - cnt_u = 0~ thì đỉnh ~u~ sẽ là đỉnh thỏa mãn.

~tot~ và mảng ~cnt~ có thể được tính dễ dàng trong ~O(N)~.

Code mẫu

#include <iostream>
#include <stdio.h>
#include <vector>
#include <cmath>
#include <math.h>
#include <map>
#include <algorithm>
#include <set>
#include <bitset>
#include <queue>
#include <cstring>
#include <stack>
#include <iomanip>
#include <assert.h>

#define BIT(x,pos) (((x)>>(pos)) & 1LL)
#define _(x) (1LL<<(x))
#define bitCnt(x) __builtin_popcountll(x)
#define turnOn(x,pos) ((x) = (_(pos)))
#define turnOff(x,pos) ((x) &= ~(_(pos)))
#define flipBit(x,pos) ((x) ^= (_(pos)))
#define lowBit(x) ((x) & (-x))
#define turnAll(x) (_(x)-1LL)

#define name "test"
#define fastIO ios::sync_with_stdio(false); cin.tie(0);

using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,ll> pil;
typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vll;

const int N = 2E6;

int f[N+9];
vector<int> adj[N+9];
int n;
int c[N+9];
vector<int> res;

void dfsDown(int u,int p)
{
    f[u] = c[u];

    for (int i = 0;i < (int)adj[u].size(); ++i)
    {
        int v = adj[u][i];
        if (v == p) continue;

        dfsDown(v, u);
        if (f[v] != c[u]) f[u] = -1;
    }
}

void ck(int u,int p)
{
    bool flag = false;

    for (int i = 0;i < (int)adj[u].size(); ++i)
    {
        int v = adj[u][i];
        if(v == p) continue;

        if (f[v] < 0) flag = true;
    }

    if (flag == false) res.push_back(u);

    if (u != p && c[p] != c[u]) return;

    int chosenNode = -1;
    for (int i = 0;i < (int)adj[u].size(); ++i)
    {
        int v = adj[u][i];
        if (v == p) continue;

        if (f[v] != c[u])
        {
            if (chosenNode < 0) chosenNode = v;
            else return;
        }
    }

    if (chosenNode > 0) ck(chosenNode, u);
}

int main()
{
    fastIO

    cin>>n;

    for (int i = 1;i < n; ++i)
    {
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    for (int i = 1;i <= n; ++i) cin>>c[i];

    try
    {
        bool flag = false;

        for (int i = 1;i+1 <= n; ++i)
            if (c[i] != c[i+1])
            {
                flag = true;
                break;
            }

        if (flag == false) throw 2;

        dfsDown(1, 1);
        ck(1, 1);
    }
    catch (int x)
    {
        if (x == 2)
        {
            cout<<"YES\n";

            for (int i = 1;i <= n; ++i) cout<<i<<" ";

            return 0;
        }
    }

    if ((int)res.size() == 0) return cout<<"NO", 0;

    cout<<"YES\n";

    sort(res.begin(),res.end());

    for (int i = 0;i < (int)res.size(); ++i) cout<<res[i]<<" ";
}

Bình luận

Hãy đọc nội quy trước khi bình luận.



  • 1
    nhatday1  đã bình luận lúc 18, Tháng 3, 2024, 7:25

    hello