题目链接
中文题意,表面平静,实则暗藏玄机,而打开本题的突破口,也确确实实就在于题目的描述:
也就是说,这张图的边的数目是确定的,并且这是一张连通图,而且图上的个点每个点连接出去的边的数目都是条,因为每个数都刚好只与个数在二进制位上差1。
那么,这张图的形态是固定的,好了,现在开始想解决问题的方法。
于是乎,我们可以贪心的,为了让字典序是最小的,所以1号点一定选的是点权0。那么接下去与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;
}