天知道我是在怎样的精神状态下写出来的。
感觉是很新奇的随机化做法()
前 $4.5$ 秒,第一个排列开始找 next_permutation 并且 check。
前 $4.5\sim 9$ 秒,最后一个排列开始找 prev_permutation 并且 check。
前 $9\sim 9.995$ 秒,对于排列随机交换位置,然后如果答案与之前相同,有 $0.9$ 的概率交换。
最后 $0.005$ 秒用来输出。
随机种子写奇怪大质数就行。
https://www.luogu.com.cn/record/155391395
#include <bits/stdc++.h>
using namespace std;
#define getchar() p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++
char buf[1000000], *p1 = buf, *p2 = buf;
template <typename T>
void read(T &x)
{
x = 0;
int f = 1;
char c = getchar();
for (; c < '0' || c > '9'; c = getchar())
if (c == '-')
f = -f;
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
x *= f;
}
template <typename T, typename... Args>
void read(T &x, Args &...y)
{
read(x);
read(y...);
}
const int inf = 1e9;
mt19937 rnd(2010111901192009);
const int ED1 = 0.45 * CLOCKS_PER_SEC;
const int ED2 = 0.9 * CLOCKS_PER_SEC;
const int ED = 0.995 * CLOCKS_PER_SEC;
int R(int l, int r) { return rnd() % (r - l + 1) + l; }
int mp[30][30];
int n, m;
int p[30];
int ap[30];
int ans = inf;
int chosen[30];
void upd(bool f = 0)
{
int tmp = 0;
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
tmp += mp[p[i]][p[j]];
for (int i = n + 1; i <= n << 1; i++)
for (int j = i + 1; j <= n << 1; j++)
tmp += mp[p[i]][p[j]];
tmp = m - tmp;
if (tmp > ans)
return;
if (tmp < ans)
{
ans = tmp;
memcpy(ap, p, sizeof(ap));
return;
}
if (!f)
{
if (R(1, 100) >= 90)
memcpy(ap, p, sizeof(ap));
}
}
void check()
{
int l = R(1, n);
int r = R(n + 1, n << 1);
swap(p[l], p[r]);
upd(1);
}
int main()
{
read(n, m);
for (int i = 1; i <= n; i++)
p[i] = i;
for (int i = 1; i <= m; i++)
{
int u, v;
read(u, v);
mp[u][v] = mp[v][u] = 1;
}
n >>= 1;
for (int i = 1; i <= n << 1; i++)
chosen[i] = (i > n);
do
{
int tot = 0;
for (int i = 1; i <= n << 1; i++)
{
if (chosen[i])
p[++tot] = i;
}
for (int i = 1; i <= n << 1; i++)
{
if (!chosen[i])
p[++tot] = i;
}
upd();
if (clock() > ED1)
break;
} while (next_permutation(chosen + 1, chosen + (n << 1) + 1));
for (int i = 1; i <= n << 1; i++)
chosen[i] = (i <= n);
do
{
int tot = 0;
for (int i = 1; i <= n << 1; i++)
{
if (chosen[i])
p[++tot] = i;
}
for (int i = 1; i <= n << 1; i++)
{
if (!chosen[i])
p[++tot] = i;
}
upd();
if (clock() > ED2)
break;
} while (prev_permutation(chosen + 1, chosen + (n << 1) + 1));
while (clock() < ED)
check();
for (int i = 1; i <= n; i++)
cout << ap[i] << " ";
cout << endl;
return 0;
}