环图应用--数组补全

数组补全

给定一个 \(1-n\) 的排列 \(f_1,f_2,f_3...f_n\)

已知,对于 \(1 \leq n,f_i \neq i\) 始终成立。

现在,因为一些原因,数组中部分元素丢失了。

请你将数组丢失的部分补全,要求数组在补全后仍然是一个 \(1-n\) 的排列,且对于 \(1 \leq n,f_i \neq i\) 均成立。

对每个未丢失的元素,由 \(i\)\(f_i\) 连接一条有向边,很容易得出原图应该是一个环图,每个结点都在环中,且入读 = 出度 = 1。

记录每个元素的出边和入边,如果无孤立点,则把环首尾连接,否则把孤立点加入任何一个环中即可。

特别的,如果图中全部都是孤立点或者环都是闭环,则孤立点单独形成一个环。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

int main ()
{
    int T; cin >> T;
    while (T --)
    {
        int n; cin >> n;
        vector<int> p(n+1, 0), q(n+1, 0); // p表示出边,q表示入边
        vector<bool> st(n+1, 0); // 是否被考虑过
        for (int i = 1; i <= n; i++)
        {
            cin >> p[i];
            q[p[i]] = i;
        }
        bool f = false; // 记录孤立点是否被加入
        for (int i = 1; i <= n; i++)
        {
            if (st[i] || !q[i]) // 以及被考虑过或者是孤立边
                continue;
                
            st[i] = true;
            int x = i, y = i; // x是环起点,y是终点
            while (q[x] && !st[q[x]])
            {
                st[q[x]] = true;
                x = q[x];
            }
            while (p[y] && !st[p[y]])
            {
                st[p[y]] = true;
                y = p[y];
            }
            if (q[x] == y) continue;
            if (!f)
            {
                f = !f;
                for (int i = 1; i <= n; i++)
                {
                    if (p[i] || q[i]) continue;
                    st[i] = true;
                    p[y] = i;
                    y = i;
                }
            }
            p[y] = x;
        }
        // 图上都是孤立点或者所有的环都是闭环,孤立点构造环
        if (!f)
        {
            int x = 0, y = 0;
            for (int i = 1; i <= n; i++)
            {
                if (p[i] || q[i]) continue;
                if (!x && !y) x = y = i;
                else
                {
                    p[y] = i;
                    y = i;
                }
            }
            p[y] = x;
        }
        for (int i = 1; i <= n; i++)
            cout << p[i] << ' ';
        cout << endl;
    }
}
posted @ 2021-08-02 15:12  Horb7  阅读(37)  评论(0编辑  收藏  举报