1. 程式人生 > 其它 >2021杭電多校賽第七場

2021杭電多校賽第七場

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