你发现 $n\leq 26$,直接考虑随机化乱搞。

由于这道题的数据比较强,所以不能硬随,要加一点优化。

第一步,你随机一些序列,取其中最优的序列开始交换。

在随机交换的过程中,为了减少陷入局部最优解的概率,在被拒绝了一定次数之后,随机交换一部分的决策,这样就会让你的随机化贪心正确率更高。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include<bits/stdc++.h>
using namespace std;
int n,m,a[105],ans[105],v[105];
vector<int> g[105];
mt19937 rd(19530615);
inline int calc(){
int as=0;
for(int i=1;i*2<=n;++i)
for(int j:g[a[i]])as+=v[j];
return as;
}
inline int calc2(){
int as=0;
for(int i=1;i*2<=n;++i)
for(int j:g[ans[i]])as+=v[j];
return as;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;++i){
int x,y;cin>>x>>y;
g[x].push_back(y);
g[y].push_back(x);
}
for(int i=1;i<=n;++i)a[i]=i;
int sans=1e7;
for(int i=1;i<=20;++i){
shuffle(a+1,a+n+1,rd);
for(int i=1;i<=n/2;++i)v[a[i]]=0;
for(int i=n/2+1;i<=n;++i)v[a[i]]=1;
int sum=calc();
if(sans>sum){
sans=sum;
for(int i=1;i<=n;++i)ans[i]=a[i];
}
}
for(int i=1;i<=n/2;++i)v[ans[i]]=0;
for(int i=n/2+1;i<=n;++i)v[ans[i]]=1;
for(int i=1;i<=n;++i)a[i]=ans[i];
int cnt=0;
while(1.0*clock()/CLOCKS_PER_SEC<=0.48){
int x=rd()%(n/2)+1,y=rd()%(n/2)+n/2+1;
swap(a[x],a[y]);swap(v[a[x]],v[a[y]]);
int sum=calc();
if(sans>sum){sans=sum;for(int i=1;i<=n;++i)ans[i]=a[i];}
else swap(a[x],a[y]),swap(v[a[x]],v[a[y]]),++cnt;
if(cnt%100==0){
for(int i=1;i<=20;++i){
int x=rd()%(n/2)+1,y=rd()%(n/2)+n/2+1;
swap(a[x],a[y]);swap(v[a[x]],v[a[y]]);
}
}
}
while(1.0*clock()/CLOCKS_PER_SEC<=0.98){
int x=rd()%(n/2)+1,y=rd()%(n/2)+n/2+1;
swap(a[x],a[y]);swap(v[a[x]],v[a[y]]);
int sum=calc();
if(sans>sum){sans=sum;for(int i=1;i<=n;++i)ans[i]=a[i];}
else swap(a[x],a[y]),swap(v[a[x]],v[a[y]]),++cnt;
if(cnt%80==0){
for(int i=1;i<=20;++i){
int x=rd()%(n/2)+1,y=rd()%(n/2)+n/2+1;
swap(a[x],a[y]);swap(v[a[x]],v[a[y]]);
}
}
}
for(int i=1;i*2<=n;++i)cout<<ans[i]<<' ';
cout<<'\n';
return 0;
}