Atcoder AGC010E :Rearranging

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/82587635

传送门

题解:
不互质的连边,联通块内部尽量小,联通块之间尽量大。

尽量大直接贪心,考虑内部如何尽量小。

我们先选取最小的,然后把与他相连的边从小到大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]<<' ';
    }
}

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/82587635