D. Nezzar and Hidden Permutations

目录

1.Problem

2.Input

3.Output

4.Examples

4.1input

4.2output

5.Code

6.Conclusion


1.Problem

Nezzar designs a brand new game "Hidden Permutations" and shares it with his best friend, Nanako.

At the beginning of the game, Nanako and Nezzar both know integers nn and mm. The game goes in the following way:

  • Firstly, Nezzar hides two permutations p1,p2,…,pnp1,p2,…,pn and q1,q2,…,qnq1,q2,…,qn of integers from 11 to nn, and Nanako secretly selects mm unordered pairs (l1,r1),(l2,r2),…,(lm,rm)(l1,r1),(l2,r2),…,(lm,rm);
  • After that, Nanako sends his chosen pairs to Nezzar;
  • On receiving those mm unordered pairs, Nezzar checks if there exists 1≤i≤m1≤i≤m, such that (pli−pri)(pli−pri) and (qli−qri)(qli−qri) have different signs. If so, Nezzar instantly loses the game and gets a score of −1−1. Otherwise, the score Nezzar gets is equal to the number of indices 1≤i≤n1≤i≤n such that pi≠qipi≠qi.

However, Nezzar accidentally knows Nanako's unordered pairs and decides to take advantage of them. Please help Nezzar find out two permutations pp and qq such that the score is maximized.

2.Input

The first line contains a single integer tt (1≤t≤5⋅1051≤t≤5⋅105) — the number of test cases.

The first line of each test case contains two integers n,mn,m (1≤n≤5⋅105,0≤m≤min(n(n−1)2,5⋅105)1≤n≤5⋅105,0≤m≤min(n(n−1)2,5⋅105)).

Then mm lines follow, ii-th of them contains two integers li,rili,ri (1≤li,ri≤n1≤li,ri≤n, li≠rili≠ri), describing the ii-th unordered pair Nanako chooses. It is guaranteed that all mm unordered pairs are distinct.

It is guaranteed that the sum of nn for all test cases does not exceed 5⋅1055⋅105, and the sum of mm for all test cases does not exceed 5⋅1055⋅105.

3.Output

For each test case, print two permutations p1,p2,…,pnp1,p2,…,pn and q1,q2,…,qnq1,q2,…,qn such that the score Nezzar gets is maximized.

4.Examples

4.1input

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

4.2output

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

5.Code

#include

#define pb push_back
#define mp make_pair
#define fi first
#define se second

using namespace std;

typedef long long ll;
typedef pair pii;
typedef pair pll;

template  bool chkmax(T &x, T y) { return x < y ? x = y, true : false; }
template  bool chkmin(T &x, T y) { return x > y ? x = y, true : false; }

int readint() {
    int x = 0, f = 1; 
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

const int MAXN = 500005;
const int MAXM = 1000005;

int n, m, tot;
int v[MAXM], nxt[MAXM], h[MAXN], f[MAXN], du[MAXN], q[MAXN], ans1[MAXN], ans2[MAXN];
bool vis[MAXN];
vector adj[MAXN];

int getf(int x) {
    return x == f[x] ? x : f[x] = getf(f[x]);
}

void addedge(int x, int y) {
    v[++tot] = y; nxt[tot] = h[x]; h[x] = tot; du[y]++;
    v[++tot] = x; nxt[tot] = h[y]; h[y] = tot; du[x]++;
}

void work() {
    n = readint(); 
    m = readint();
    
    for (int i = 1; i <= n + 1; i++) 
        h[i] = du[i] = vis[i] = 0; 
    
    tot = 0;

    for (int i = 1; i <= n; i++) {
        adj[i].clear();
        f[i] = i;
    }

    int x, y;

    for (int i = 1; i <= m; i++) {
        x = readint(); 
        y = readint();
        adj[x].pb(y);
        adj[y].pb(x);
    }

    for (int i = 1; i <= n; i++) {
        vis[i] = 1;

        for (auto v : adj[i]) 
            vis[v] = 1;

        int pl = 0;

        for (int j = 1; j <= adj[i].size() + 2; j++) 
            if (!vis[j]) 
                pl = j;

        if (pl <= n) {
            int fx = getf(i), fy = getf(pl);
            if (fx != fy) 
                f[fx] = fy, addedge(i, pl);
        }

        vis[i] = 0;

        for (auto v : adj[i]) 
            vis[v] = 0;
    }

    int front = 0, rear = 0, cnt = 0;

    for (int i = 1; i <= n; i++) 
        if (du[i] == 1) 
            q[rear++] = i;

    for (int i = 1; i <= n; i++) 
        if (du[i] == 0) 
            ans1[i] = ans2[i] = ++cnt;

    while (front < rear) {
        int t = q[front++], to;

        if (vis[t]) 
            continue;

        for (int p = h[t]; p; p = nxt[p]) 
            if (!vis[v[p]]) 
                to = v[p];

        vis[to] = 1;
        vector vec(1, to);

        for (int p = h[to]; p; p = nxt[p]) {
            if (!vis[v[p]] && du[v[p]] == 1) {
                vec.pb(v[p]);
                vis[v[p]] = 1;
            }
        }

        for (int i = 0; i < vec.size(); i++) 
            ans1[vec[i]] = cnt + i + 1;

        for (int i = 1; i < vec.size(); i++) 
            ans2[vec[i]] = cnt + i;

        ans2[to] = cnt + vec.size();
        cnt += vec.size();

        for (int p = h[to]; p; p = nxt[p]) 
            if (!vis[v[p]] && (--du[v[p]]) == 1) 
                q[rear++] = v[p];
    }

    for (int i = 1; i <= n; i++) 
        printf("%d ", ans1[i]);

    printf("\n");

    for (int i = 1; i <= n; i++) 
        printf("%d ", ans2[i]);

    printf("\n");
}

int main() {
    int T = readint();

    while (T--) 
        work();

    return 0;
}

6.Conclusion

这段代码实现了一个图论算法。具体来说,它解决了一个图的遍历和连通性问题。以下是代码的主要功能:

1.通过 readint 函数读取输入。
2.使用并查集维护图中的连通分量,并在发现新的边时将其添加到图中。
3.找到每个节点的度数,并将度数为1的节点加入队列。
4.从队列中取出节点,沿着图的边进行遍历,更新节点的连通分量,并将度数为1的相邻节点加入队列。
5.输出两个排列,其中第一个排列表示节点在第一次遍历时的顺序,第二个排列表示节点在第二次遍历时的顺序。

总体而言,这段代码对一个无向图进行了一系列遍历和处理,最终输出了两个排列,表示两次遍历的顺序。

你可能感兴趣的:(CodeForces,开发语言,c++,数据结构,算法)