QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#344130#8055. Balanceucup-team045WA 156ms3656kbC++2012.9kb2024-03-03 16:40:152024-03-03 16:40:16

Judging History

你现在查看的是最新测评结果

  • [2024-03-03 16:40:16]
  • 评测
  • 测评结果:WA
  • 用时:156ms
  • 内存:3656kb
  • [2024-03-03 16:40:15]
  • 提交

answer

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
using LL = long long;

struct Edge{
    int to;
    int id;
    operator int() const { return to; }
};

struct LowLink{
    int n;
    vector<vector<Edge> > g;
    vector<int> in, out, low;
    int ts;
    // map<int, int> bridge;

    LowLink(const vector<vector<Edge> > &g) : n(int(g.size()) - 1), g(g) {
        ts = 0;
        in.assign(n + 1, 0);
        out.assign(n + 1, 0);
        low.assign(n + 1, 0);
        for(int i = 1; i <= n; i++){
            if (in[i] == 0){
                tarjan(i, -1);
            }
        }
        
        id.assign(n + 1, 0);
        cnt = 0;
        for(int i = 1; i <= n; i++){
            if (id[i] == 0){
                dfs(i, -1);
            }
        }
        group.resize(cnt + 1);;
        for(int i = 1; i <= n; i++){
            group[id[i]].push_back(i);
        }
    }

    void tarjan(int u, int from){
        in[u] = low[u] = ++ts;
        for(auto j : g[u]){
            if (!in[j]){
                tarjan(j, j.id);
                low[u] = min(low[u], low[j]);
                // if (low[j] > in[u]){
                    // bridge[j.id] = j;
                // }
            }
            else if (j.id != from) low[u] = min(low[u], in[j]);
        }
        out[u] = ts;
    }

    int cnt;
    vector<vector<int> > group;
    vector<int> id;

    void dfs(int u, int fa){
        if (fa != -1 && low[u] <= in[fa]){
            id[u] = id[fa];
        }
        else{
            id[u] = ++cnt;
        }
        for(auto j : g[u]){
            if (id[j] == 0){
                dfs(j, u);
            }
        }
    }

};

struct HLD{
    int n;
    vector<int> sz, top, dep, fa, in, out, seq;
    vector<vector<int> > g;
    int ts;

    HLD(const vector<vector<int> > &g, int root = 1) : n(int(g.size()) - 1), g(g)  {
        ts = 0;
        sz.resize(n + 1);
        top.resize(n + 1);
        dep.resize(n + 1);
        fa.resize(n + 1);
        in.resize(n + 1);
        out.resize(n + 1);
        seq.resize(n + 1);
        dep[root] = 1;
        top[root] = root;
        dfs_sz(root);
        dfs_hld(root);
    }

    void dfs_sz(int u){
        if (fa[u]){
            for(auto it = g[u].begin(); it != g[u].end(); it++){
                if (*it == fa[u]){
                    g[u].erase(it);
                    break;
                }
            }
        }
        sz[u] = 1;
        for(auto &j : g[u]){
            fa[j] = u;
            dep[j] = dep[u] + 1;
            dfs_sz(j);
            sz[u] += sz[j];
            if (sz[j] > sz[g[u][0]])
                swap(j, g[u][0]);
        }
    }

    void dfs_hld(int u){
        in[u] = ++ts;
        seq[in[u]] = u;
        for (auto j : g[u]){
            top[j] = (j == g[u][0] ? top[u] : j);
            dfs_hld(j);
        }
        out[u] = ts;
    }

    int lca(int u, int v){
        while (top[u] != top[v]){
            if (dep[top[u]] > dep[top[v]]){
                u = fa[top[u]];
            } 
            else{
                v = fa[top[v]];
            }
        }
        return dep[u] < dep[v] ? u : v;
    }

    int dist(int u, int v){
        return dep[u] + dep[v] - 2 * dep[lca(u, v)];
    }

    bool in_subtree(int u, int v){
        return in[v] <= in[u] && in[u] <= out[v];
    }
    
    int jump(int u, int k) {
        if (dep[u] < k){
            return -1;
        }
        int d = dep[u] - k;
        while (dep[top[u]] > d){
            u = fa[top[u]];
        }
        return seq[in[u] - dep[u] + d];
    }
    
    int rooted_lca(int a, int b, int c){
        return lca(a, b) ^ lca(b, c) ^ lca(c, a);
    }

    template<typename Q>
    void modify_path(int u, int v, const Q &q, bool edge = false){
        while(top[u] != top[v]){
            if (dep[top[u]] < dep[top[v]]) swap(u, v);
            q(in[top[u]], in[u]);
            u = fa[top[u]];        
        }
        if (dep[u] > dep[v]) swap(u, v);
        q(in[u] + edge, in[v]);
    }

    template<typename Q>
    void modify_subtree(int u, const Q &q){
        q(in[u], out[u]);
    }  

    template<typename T, typename Q>
    T query_path(int u, int v, const Q &q, bool edge = false){
        T ret = T();
        while(top[u] != top[v]){
            if (dep[top[u]] < dep[top[v]]) swap(u, v);
            ret = q(in[top[u]], in[u]) + ret;
            u = fa[top[u]];
        }
        if (dep[u] > dep[v]) swap(u, v);
        return q(in[u] + edge, in[v]) + ret;
    }

    template<typename T, typename Q>
    T query_subtree(int u, const Q &q){
        return q(in[u], out[u]);
    }

    template<typename T, typename Q, typename F>
    T query_path_noncommutative(int u, int v, const Q &q, const F &f, bool edge = false){
        T left = T(), right = T();
        while(top[u] != top[v]){
            if (dep[top[u]] < dep[top[v]]) swap(u, v), swap(left, right);
            left = q(in[top[u]], in[u]) + left;
            u = fa[top[u]];
        }
        if (dep[u] > dep[v]) swap(u, v), swap(left, right);
        return f(left, q(in[u] + edge, in[v]) + right);
    }
    
    pair<vector<int>, vector<pair<int, int> > > compress(vector<int> v){
        auto cmp = [&](int a, int b) { return in[a] < in[b]; };
        sort(v.begin(), v.end(), cmp);
        v.erase(unique(v.begin(), v.end()), v.end());
        const int k = (int)v.size();
        for(int i = 0; i + 1 < k; i++){
            v.push_back(lca(v[i], v[i + 1]));
        }
        sort(v.begin(), v.end(), cmp);
        v.erase(unique(v.begin(), v.end()), v.end());
        vector<pair<int, int> > edges;
        vector<int> stk;
        for(auto x : v){
            while(!stk.empty() && out[stk.back()] < in[x]){
                stk.pop_back();
            }
            if (!stk.empty()){
                edges.push_back({stk.back(), x});
            }
            stk.push_back(x);
        }
        return {v, edges};
    }

};

int main(){

#ifdef LOCAL
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
#endif

    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);

    int T;
    cin >> T;
    while(T--){
        int n, m;
        cin >> n >> m;
        vector<vector<Edge> > g(n + 1);
        for(int i = 0; i < m; i++){
            int a, b;
            cin >> a >> b;
            g[a].push_back({b, i});
            g[b].push_back({a, i});
        }
        vector<int> cnt(n + 1);
        for(int i = 1; i <= n; i++){
            int x;
            cin >> x;
            cnt[x] += 1;
        }
        vector<int> nums;
        vector<int> id(n + 1);
        for(int i = 1; i <= n; i++){
            if (cnt[i]){
                nums.push_back(i);
                id[nums.size()] = i;
            }
        }
        if (nums.size() == 1){
            cout << "Yes" << '\n';
            for(int i = 1; i <= n; i++){
                cout << nums[0] << " \n"[i == n];
            }
            continue;
        }

        LowLink lk(g);
        const int s = (int)lk.group.size() - 1;
        vector<vector<int> > ng(s + 1);
        vector<int> sz(s + 1);
        for(int i = 1; i <= n; i++){
            for(auto [j, id] : g[i]){
                if (lk.id[i] != lk.id[j]){
                    ng[lk.id[i]].push_back(lk.id[j]);
                }
            }
        }

        HLD hld(ng);

        vector<int> dp1(s + 1), dp2(s + 1);
        vector<int> pre1(s + 1), pre2(s + 1);
        vector<int> target1(n + 1), target2(n + 1);
        vector<vector<int> > pos1(nums.size() + 1);
        vector<vector<int> > pos2(nums.size() + 1);

        {
            int sum = 0;
            for(int i = 0; i < nums.size(); i++){
                sum += cnt[nums[i]];
                target1[i + 1] = sum;
            }

            auto dfs = [&](auto &&dfs, int u, int fa) -> void {
                sz[u] = lk.group[u].size();
                for(auto j : ng[u]){
                    if (j == fa) continue;
                    dfs(dfs, j, u);
                    sz[u] += sz[j];
                    if (dp1[j] > dp1[u]){
                        dp1[u] = dp1[j];
                        pre1[u] = j;
                    }
                }
                if (target1[dp1[u] + 1] == sz[u]){
                    dp1[u] += 1;
                    pos1[dp1[u]].push_back(u);
                }
            };

            dfs(dfs, 1, -1);

        }
        {
            int sum = 0;
            reverse(nums.begin(), nums.end());
            for(int i = 0; i < nums.size(); i++){
                sum += cnt[nums[i]];
                target2[i + 1] = sum;
            }
            reverse(nums.begin(), nums.end());

            auto dfs = [&](auto &&dfs, int u, int fa) -> void {
                sz[u] = lk.group[u].size();
                for(auto j : ng[u]){
                    if (j == fa) continue;
                    dfs(dfs, j, u);
                    sz[u] += sz[j];
                    if (dp2[j] > dp2[u]){
                        dp2[u] = dp2[j];
                        pre2[u] = j;
                    }
                }
                if (target2[dp2[u] + 1] == sz[u]){
                    dp2[u] += 1;
                    pos2[dp2[u]].push_back(u);
                }
            };

            dfs(dfs, 1, -1);
            
        }

        vector<int> ans(s + 1);
        vector<int> path;

        auto get_path = [&](int p, int k, vector<int> &target, vector<int> &pre){
            vector<int> path;
            path.push_back(hld.fa[p]);
            ans[hld.fa[p]] = nums[k];
            path.push_back(p);
            int cur = k;
            ans[p] = nums[cur - 1];
            while(cur != 1 && pre[p]){
                p = pre[p];
                if (target[cur - 1] == sz[p]){
                    cur -= 1;
                }
                ans[p] = nums[cur - 1];
                path.push_back(p);
            }
            return path;
        };

        if (!pos1[nums.size() - 1].empty()){
            int p = pos1[nums.size() - 1][0];
            path = get_path(p, (int)nums.size() - 1, target1, pre1);
        }
        else if (!pos2[nums.size() - 1].empty()){
            reverse(nums.begin(), nums.end());
            int p = pos2[nums.size() - 1][0];
            path = get_path(p, (int)nums.size() - 1, target2, pre2);
        }
        else{
            for(int i = 1; i <= nums.size(); i++){
                sort(pos1[i].begin(), pos1[i].end(), [&](int a, int b){
                    return hld.in[a] < hld.in[b];
                });
                sort(pos2[i].begin(), pos2[i].end(), [&](int a, int b){
                    return hld.in[a] < hld.in[b];
                });
            }

            for(int i = 1; i + 1 <= nums.size(); i++){
                if (!path.empty()) break;
                auto &v = pos2[nums.size() - 1 - i];
                if (v.empty() || pos1[i].empty()) continue;
                for(auto x : pos1[i]){
                    if (!path.empty()) break;
                    if (hld.in[v.back()] > hld.out[x]){
                        int p1 = x, p2 = v.back();
                        path = get_path(p1, i, target1, pre1);
                        reverse(nums.begin(), nums.end());
                        auto path2 = get_path(p2, (int)nums.size() - i - 1, target2, pre2);
                        path.insert(path.end(), path2.begin(), path2.end());
                    }
                }
            }

            for(int i = 1; i + 1 <= nums.size(); i++){
                if (!path.empty()) break;
                auto &v = pos1[nums.size() - 1 - i];
                if (v.empty() || pos2[i].empty()) continue;
                for(auto x : pos2[i]){
                    if (!path.empty()) break;
                    if (hld.in[v.back()] > hld.out[x]){
                        int p1 = v.back(), p2 = x;
                        path = get_path(p1, i, target1, pre1);
                        reverse(nums.begin(), nums.end());
                        auto path2 = get_path(p2, (int)nums.size() - i - 1, target2, pre2);
                        path.insert(path.end(), path2.begin(), path2.end());
                    }
                }
            }
        }

        if (path.empty()){
            cout << "No" << '\n';
        }
        else{

            auto dfs = [&](auto &&dfs, int u) -> void {
                for(auto j : ng[u]){
                    if (!ans[j]){
                        ans[j] = ans[u];
                        dfs(dfs, j);
                    }
                }
            };

            for(auto x : path){
                dfs(dfs, x);
            }

            cout << "Yes" << '\n';
            for(int i = 1; i <= n; i++){
                cout << ans[lk.id[i]] << " \n"[i == n];
            }
        }
    }

}

详细

Test #1:

score: 100
Accepted
time: 1ms
memory: 3648kb

input:

5
5 4
1 2
2 3
3 4
4 5
1 2 3 4 5
5 4
1 2
1 3
1 4
1 5
1 2 3 4 5
5 4
1 2
1 3
1 4
1 5
1 2 2 2 3
5 6
1 2
1 2
2 3
3 4
4 5
3 5
1 2 1 2 1
2 2
1 2
1 2
1 2

output:

Yes
5 4 3 2 1
No
Yes
2 1 2 2 3
Yes
2 2 1 1 1
No

result:

ok ok (5 test cases)

Test #2:

score: -100
Wrong Answer
time: 156ms
memory: 3656kb

input:

100000
4 3
4 2
1 3
2 1
2 1 3 2
5 7
2 5
5 3
2 3
5 1
4 3
2 4
4 3
1 3 1 1 2
3 2
2 1
2 3
1 1 1
4 7
3 4
1 4
2 3
4 3
4 2
3 1
4 3
2 3 3 2
4 6
2 4
3 1
1 2
1 2
2 3
4 2
1 1 3 3
4 7
3 2
4 2
1 2
3 4
3 2
2 4
3 4
2 1 1 1
5 5
3 2
1 5
4 5
4 3
2 1
1 2 2 3 2
3 5
2 3
1 3
3 1
3 1
2 1
3 2 3
2 3
2 1
2 1
1 2
1 1
2 3
2 1
1...

output:

Yes
2 2 3 1
No
Yes
1 1 1
No
No
Yes
2 1 1 1
No
No
Yes
1 1
Yes
1 1
Yes
1 1
Yes
1 1 1 1
No
Yes
1 1 1 1 1
Yes
1 3 1 1 1
Yes
1 1 1
Yes
2 1
Yes
1 1 1 1 1
Yes
2 1
No
Yes
1 1
Yes
1 1 1
Yes
1 1
Yes
1 1 1 1
Yes
1 1
Yes
2 2 2 2 2
Yes
1 1 1 1 1
Yes
1 1
Yes
1 1 1 2
No
Yes
1 1
No
Yes
1 1
No
No
No
Yes
2 1 1 1 1
Ye...

result:

wrong answer 1-th smallest numbers are not same (test case 479)