2021杭电多校赛第七场


2021“MINIEYE杯”中国大学生算法设计超级联赛(7)

Link with Limit

根据极限的定义我们可以得出如下结论:

\(\bullet\) 题目所给\(f_n(x)\)必成环(包括自环)。

\(\bullet\) 对于属于当前环的\(x\),它们的极限相同。

那么我们只需要让每个\(i\)\(f[i]\)连边,求出每个环的平均值比较是否相同即可。

同时为了避免精度问题,我在判断时分别存储了分子分母。

循环

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int adj[MAXN], col[MAXN];
int main(int argc, char *argv[]) {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int T;
    cin >> T;
    while (T--) {
        memset(col, 0, sizeof(col));
        int n;
        cin >> n;
        for (int i = 1; i <= n; ++i) {
            cin >> adj[i];
        }
        bool f = true;
        int idx = 0, up = 0, down = 0;
        // up为分子
        // down为分母
        // solve用于更新up和down
        auto solve = [&](int &x, int &y) -> void {
            if (!up) {
                up = x;
                down = y;
            }
            if (up * y != down * x) {
                f = false;
            }
        };
        for (int i = 1; i <= n && f; ++i) {
            if (col[i]) continue;
            ++idx;
            int u = i;
            while (!col[u]) {
                col[u] = idx;
                u = adj[u];
                if (col[u] == idx) { // 下一个点已经访问过代表出现环
                    int x = 0, y = 0;
                    // x为当前环的权值
                    // y为当前环的点数
                    for (int v = u; ; ) { // 遍历环
                        x += adj[v], ++y;
                        v = adj[v];
                        if (v == u) {
                            solve(x, y);
                            break;
                        }
                    }
                }
            }
        }
        cout << (f ? "YES" : "NO") << '\n';
    }
    system("pause");
    return 0;
}

tarjan

需要注意的是\(tarjan\)筛出的一些强联通分量是不需要的,需要过滤掉。

如图,\(tarjan\)筛出的\(4\)号点是不需要的。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int f[MAXN], w[MAXN]; // w表示每个scc的权值
stack<int> stk; bool ins[MAXN];
vector<int> e[MAXN], scc[MAXN];
int low[MAXN], dfn[MAXN], idx;
int sz[MAXN], belong[MAXN], sccn;
void dfs(int u) {
    dfn[u] = low[u] = ++idx;
    stk.push(u), ins[u] = true;
    for (int v: e[u]) {
        if (!dfn[v]) {
            dfs(v);
            low[u] = min(low[u], low[v]);
        }
        else if (ins[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if (low[u] == dfn[u]) {
        ++sccn;
        int top;
        do {
            top = stk.top();
            stk.pop();
            ++sz[sccn];
            ins[top] = false;
            belong[top] = sccn;
        } while (u ^ top);
    }
}
void tarjan(int n) {
    for (int i = 1; i <= n; ++i) {
        if (!dfn[i]) {
            dfs(i);
        }
    }
}
void init() {
    idx =  0;
    memset(dfn, 0, sizeof(dfn));
    memset(low, 0, sizeof(low));
    sccn = 0;
    memset(sz, 0, sizeof(sz));
    while (!stk.empty()) stk.pop();
    memset(ins, false, sizeof(ins));
    memset(belong, 0, sizeof(belong));
    memset(w, 0, sizeof(w));
}
int main(int argc, char *argv[]) {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int T;
    cin >> T;
    while (T--) {
        init();
        int n;
        cin >> n;
        for (int i = 1; i <= n; ++i) {
            e[i].clear();
            scc[i].clear();
        }
        for (int i = 1; i <= n; ++i) {
            cin >> f[i];
            e[i].push_back(f[i]);
        }
        tarjan(n);
        for (int i = 1; i <= n; ++i) {
            w[belong[i]] += f[i];
            scc[belong[i]].push_back(i);
        }
        vector<pair<int, int>> V;
        for (int i = 1; i <= sccn; ++i) {
            // 如果是单点并且是自环
            if (sz[i] == 1 && e[scc[i][0]][0] == scc[i][0]) {
                V.push_back({w[i], 1});
            }
            else if (sz[i] > 1) {
                V.push_back({w[i], sz[i]});
            }
        }
        bool f = true;
        for (int i = 1; i < V.size(); ++i) {
            if (V[i].first * V[i - 1].second ^ V[i].second * V[i - 1].first) {
                f = false;
            }
        }
        cout << (f ? "YES" : "NO") << '\n';
    }
    system("pause");
    return 0;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM