CF1804E Routing
RMJ 真的完蛋了……
题意
给定一个
你需要构造一个序列
- 对于任意
1\leq i\leq n ,无向边(i,a_i) 存在; - 对于任意
x,y(x\neq y) ,初始时i 为x ,然后不断让i 变为a_i ,存在某个i ,使得y 是其一个邻居。
或报告无解。
分析
首先转换题意,可以按照给的方式构造一个基环树,且环上挂的树高最多为
看到数据范围
仔细思考了一下,感觉是很套路的 dp。直接找环可能有困难,所以我们考虑先找一条链,在把首位接上。直接设
找答案可以直接每次枚举可能终点,让后从他下一个点连过来。
总复杂度
code
#include <bits/stdc++.h>
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2")
#define LL long long
#define writesp(x) write(x), putchar(' ')
#define writeln(x) write(x), putchar('\n')
#define FileIO(ch) freopen(ch".in", "r", stdin), freopen(ch".out", "w", stdout)
using namespace std;
namespace IO {
char ibuf[(1 << 20) + 1], *iS, *iT;
#if ONLINE_JUDGE
#define gh() (iS == iT ? iT = (iS = ibuf) + fread(ibuf, 1, (1 << 20) + 1, stdin), (iS == iT ? EOF : *iS++) : *iS++)
#else
#define gh() getchar()
#endif
inline long long read() {
char ch = gh();
long long x = 0;
bool t = 0;
while (ch < '0' || ch > '9') t |= ch == '-', ch = gh();
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = gh();
return t ? ~(x - 1) : x;
}
template <typename _Tp>
inline void write(_Tp x) {
static char stk[64], *top = stk;
if (x < 0) {
x = ~(x - 1);
putchar('-');
}
do *top++ = x % 10, x /= 10;
while (x);
while (top != stk) putchar((*--top) | 48);
}
}
using IO::read;
using IO::write;
const int maxn(25), maxb((1 << 20) + 7);
int n, m, g[maxn], f[maxb], p[maxn];
inline int lowbit (int x) { return x & (-x); }
int main() {
n = read(), m = read();
for (int i = 1; i <= m; i++) {
int u = read(), v = read();
g[u] |= 1 << v - 1;
g[v] |= 1 << u - 1;
}
for (int i = 1; i <= n; i++) f[1 << i - 1] = 1 << i - 1;
for (int s = 0; s < (1 << n); s++) {
if (__builtin_popcount(s) < 2) continue;
for (int i = 1; i <= n; i++) {
if (s >> i - 1 & 1) {
if ((1 << i - 1) == lowbit(s)) continue;
if (f[s ^ (1 << i - 1)] & g[i]) f[s] |= (1 << i - 1);
}
}
}
for (int s = 0; s < (1 << n); s++) {
bool flg = 1;
int x = __lg(lowbit(s)) + 1;
if (!(f[s] & g[x])) continue;
for (int i = 1; i <= n; i++) {
if (s >> i - 1 & 1) continue;
if (!(g[i] & s)) { flg = 0; break; }
}
if (!flg) continue;
for (int i = 1; i <= n; i++) if (!(s >> i - 1 & 1)) p[i] = __lg(lowbit(s & g[i])) + 1;
int t = s;
while (t) {
for (int i = 1; i <= n; i++) if ((f[t] >> i - 1 & 1) && (g[x] >> i - 1 & 1)) {
p[x] = i, t ^= (1 << i - 1), x = i;
break;
}
}
break;
}
if (!p[1]) return puts("No");
puts("Yes");
for (int i = 1; i <= n; i++) writesp(p[i]);
}
// I love WHQ!