题解:
不互质的连边,联通块内部尽量小,联通块之间尽量大。
尽量大直接贪心,考虑内部如何尽量小。
我们先选取最小的,然后把与他相连的边从小到大dfs,肯定形成若干联通块。然后贪心就跟上面一样了。
#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;
typedef queue <int> Que;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=2e3+50;
int n,vis[N],a[N];
vector <int> edge[N];
inline Que dfs(int x) {
vis[x]=1;
vector <Que> q;
priority_queue <pii> q2;
for(int e=0;e<edge[x].size();e++) {
int v=edge[x][e]; if(vis[v]) continue;
q.push_back(dfs(v));
}
Que now; now.push(x);
for(int i=0;i<q.size();++i) q2.push(pii(q[i].front(),i));
while(!q2.empty()) {
int u=q2.top().second; q2.pop();
now.push(q[u].front());
q[u].pop();
if(!q[u].empty()) q2.push(pii(q[u].front(),u));
}
return now;
}
int main() {
n=rd();
for(int i=1;i<=n;i++) a[i]=rd();
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(__gcd(a[i],a[j])!=1) edge[i].push_back(j), edge[j].push_back(i);
for(int i=1;i<=n;i++) sort(edge[i].begin(),edge[i].end()), edge[0].push_back(i);
Que tq=dfs(0);
while(!tq.empty()) {
int u=tq.front(); tq.pop();
if(u) cout<<a[u]<<' ';
}
}