牛客国庆集训派对Day5 A.璀璨光滑

首先我们可以确认 1的值一定是0

题目要求的是 有边的两个点所代表的值二进制有一位不同(即有边相连的两个值二进制所包含的1的个数相差为1)

所以我们通过他给你的图进行BFS 把原图分为一圈一圈的 并且先给每一个点赋一个初值

这样每一圈内的值二进制所包含的1的个数往外递增且同一圈内值二进制所包含的1的个数是相等的 目前我们就得到了题目的一个可行解

题目追加要求最小字典序 我们发现把这2^n个数二进制表示出来 则有n列 任意两列之间的交换是不会影响值二进制中1的个数且符合边关系的

即交换二进制中的任意两列不会影响答案的正确性

所以我们就可以通过排列这个二维数组的字典序来得到 答案的最小字典序

#include<bits/stdc++.h>
using namespace std;

inline void splay(int &v)
{
        v = 0;
        char c = 0;
        int p = 1;
        while (c < '0' || c > '9')
        {
                if (c == '-')
                {
                        p = -1;
                }
                c = getchar();
        }
        while (c >= '0' && c <= '9')
        {
                v = (v << 3) + (v << 1) + c - '0';
                c = getchar();
        }
        v *= p;
}
const int N = 280000;
int n, m, dp[N], q[N], fir[N], sz, to[5000000], nxt[5000000], vis[N], inque[N];
struct Q
{
        bool s[N];
        int id;
} f[20];
void add(int x, int y)
{
        nxt[++sz] = fir[x], fir[x] = sz, to[sz] = y;
}
bool cmp(Q a, Q b)
{
        for (int i = 1; i <= (1 << n); i++)
        {
                if (a.s[i] != b.s[i])
                {
                        return a.s[i] > b.s[i];
                }
        }
    return true;
}
int main()
{
#ifdef CX_TEST
        freopen("E:\program--GG\test_in.txt", "r", stdin);
#endif
        int T;
        cin >> T;
        while (T--)
        {
                cin >> n >> m;
                for (int i = 1; i <= (1 << n); i++)
                {
                        inque[i] = vis[i] = fir[i] = dp[i] = 0;
                }
                sz = 0;
                for (int i = 1, u, v; i <= m; i++)
                {
                        splay(u), splay(v);
                        add(u, v), add(v, u);
                }
                for (int i = 1; i <= (1 << n); i++)
                {
                        dp[i] = 0;
                }
                int t = 0;
                vis[1] = 1;
                int hd = 0, tl = 0;
                for (int u = fir[1]; u; u = nxt[u])
                {
                        dp[to[u]] = 1 << (t++);
                        q[++tl] = to[u];
                }
                while (hd != tl)
                {
                        int v = q[++hd];
                        vis[v] = 1;
                        for (int u = fir[v]; u; u = nxt[u])
                        {
                                if (!vis[to[u]])
                                {
                                        dp[to[u]] |= dp[v];
                                        if (!inque[to[u]])
                                        {
                                                q[++tl] = to[u];
                                                inque[to[u]] = 1;
                                        }
                                }
                        }
                }
                for (int i = 0; i < n; i++)
                {
                        f[i].id = i;
                }
                for (int i = 1; i <= (1 << n); i++)
                {
                        for (int j = 0; j < n; j++)
                        {
                                f[j].s[i] = dp[i] >> j & 1;
                        }
                }
                sort(f, f + n, cmp);
                for (int i = 1; i <= (1 << n); i++)
                {
                        int ret = 0;
                        for (int j = 0; j < n; j++)
                        {
                                if (f[j].s[i])
                                {
                                        ret |= (1 << j);
                                }
                        }
                        printf("%d%c", ret, " 
"[i == (1 << n)]);
                }
        }
}
View Code
原文地址:https://www.cnblogs.com/Aragaki/p/9746452.html