璀璨光滑【牛客】【题意解析+BFS+贪心】

题目链接



中文题意,表面平静,实则暗藏玄机,而打开本题的突破口,也确确实实就在于题目的描述:

    也就是说,这张图的边的数目是确定的,并且这是一张连通图,而且图上的2^n个点每个点连接出去的边的数目都是n条,因为每个数都刚好只与n个数在二进制位上差1。

    那么,这张图的形态是固定的,好了,现在开始想解决问题的方法。

    于是乎,我们可以贪心的,为了让字典序是最小的,所以1号点一定选的是点权0。那么接下去与1号点相连的点肯定是2^{x}, 0 \leq x \leq n -1,那么我们不妨先假设给他们赋值,就先随便的给他们找一组可行解,于是,我们可以确定接下去的整张图,因为其他的点可以由这几个点得来,而且一个点从两个已知点权的点到达之后,该点的点权也是唯一确定的。所以,我们利用分层图的思想,这里就可以用bfs的方式来往下跑下去了。

    现在,我们确定了一组解,但这组解不一定是最贪心的,现在我们想字典序最小的办法,可以看到,二进制中第ith位的n个数如果相互交换位置,是不会影响图的形状的,所以我们可以在这里贪心。

    对于n个二进制位,我们尽可能的让点的点权是靠前的,并且不能改变图的形状,所以我们可以将每一个二进制位上有哪些点记录下来,让点的标号小的尽可能的拿小的点权来进行操作。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 27e4 + 7;
int N, _UP, M, ans[maxN], vis[maxN], que[maxN], top, tail;
vector<int> E[maxN];
bitset<maxN> a[19];
bool cmp (bitset<maxN> e1, bitset<maxN> e2) { for(int i=1; i<=_UP; i++) if(e1.test(i) ^ e2.test(i)) return e1.test(i) > e2.test(i); return false; }
int main()
{
    int T; scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &N, &M); _UP = 1 << N;  //M == N * (1 << N) / 2
        for(int i=1; i<=_UP; i++) { E[i].clear(); vis[i] = ans[i] = 0; }
        for(int i=0; i<N; i++) a[i].reset();
        for(int i=1, u, v; i<=M; i++)
        {
            scanf("%d%d", &u, &v);
            E[u].push_back(v); E[v].push_back(u);
        }
        vis[1] = 2; top = tail = 0;
        int len = (int)E[1].size(), u, v;
        for(int i=0; i<len; i++)
        {
            v = E[1][i];
            ans[v] = 1 << i;
            vis[v] = 2;
            que[tail++] = v;
        }
        while(top < tail)
        {
            u = que[top++];
            len = (int)E[u].size();
            for(int i=0; i<len; i++)
            {
                v = E[u][i];
                if(vis[v] == 2) continue;
                ans[v] |= ans[u];
                vis[v]++;
                if(vis[v] == 1) que[tail++] = v;
            }
        }
        for(int i=2; i<=_UP; i++)
        {
            for(int j=0; j<N; j++)
            {
                if((ans[i] >> j) & 1) a[j].set(i);
            }
        }
        sort(a, a + N, cmp);
        for(int i=1, val; i<=_UP; i++)
        {
            val = 0;
            for(int j=0; j<N; j++) if(a[j].test(i)) val |= 1 << j;
            printf("%d%c", val, i == _UP ? '\n' : ' ');
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/107383735