直接搜感觉会T
折半搜一下,meet in middle,位运算可以省掉一个n
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 30;
int n,m,al;
int s[maxn],siz[1<<15];
vector<int>V1[maxn],V2[maxn];
vector<int>s1[maxn],s2[maxn];
int ansc,ans;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y; scanf("%d%d",&x,&y);
s[x]|=1<<y-1,s[y]|=1<<x-1;
}
m=n>>1,al=(1<<m)-1;
for(int i=0;i<=al;i++)
for(int j=0;j<m;j++) if(i>>j&1) siz[i]++;
for(int i=0;i<=al;i++) if(i&1)
{
int now=0,n1=0,ii=i^al;
for(int j=1;j<=m;j++) if(i>>j-1&1)
now+=siz[s[j]&i],n1++;
for(int j=1;j<=m;j++) if(ii>>j-1&1)
now+=siz[s[j]&ii];
V1[n1].push_back(i); s1[n1].push_back(now>>1);
}
for(int i=0;i<=al;i++)
{
int now=0,n1=0,ii=i^al;
for(int j=1;j<=m;j++) if(i>>j-1&1)
now+=siz[s[m+j]>>m&i],n1++;
for(int j=1;j<=m;j++) if(ii>>j-1&1)
now+=siz[s[m+j]>>m&ii];
V2[n1].push_back(i); s2[n1].push_back(now>>1);
}
ansc=s1[m][0],ans=al;
for(int i=0;i<=m;i++)
{
for(int j=0;j<V1[i].size();j++)
{
int x=V1[i][j],xx=x^al,cx=s1[i][j];
for(int k=0;k<V2[m-i].size();k++)
{
int y=V2[m-i][k],yy=y^al,cc=s2[m-i][k]+cx;
for(int l=1;l<=m;l++) if(x>>l-1&1)
cc+=siz[s[l]>>m&y];
for(int l=1;l<=m;l++) if(xx>>l-1&1)
cc+=siz[s[l]>>m&yy];
if(ansc<cc) ansc=cc,ans=x|(y<<m);
}
}
}
for(int i=1;i<=n;i++) if(ans>>i-1&1) printf("%d ",i);
return 0;
}