標籤:操作 char define href ice etc push fine operator
題面
傳送門
思路
首先,一個顯然的結論是:Alice調整過後的序列中任意兩個不互質的數的相對順序無法改變
那麼我們可以以這個性質為突破口
我們在兩個不互質的權值的點之間連一條邊(沒錯這是個圖論題!!!),那麼每個聯通塊的一個拓撲序就會是這個塊最終被Bob變成的樣子
顯然,Alice可以貪心操作,使得這個拓撲序中越小的越靠前
那麼我們把所有數從小到大排序,然後從小的開始dfs,每次dfs時從最小的開始先走,得到一個$DAG$
然後把所有的$DAG$的拓撲排序的那個隊列插到一個堆裡面,每次取出最小的,就是Bob得到的序列的當前這一位
(相當於是並行做拓撲排序啦)
Code
給給全真給給
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cassert>#include<cmath>#include<queue>#define ll long longusing namespace std;inline int read(){ int re=0,flag=1;char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-') flag=-1; ch=getchar(); } while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar(); return re*flag;}int n,g[2010][2010],a[2010],vis[2010],in[2010];int first[2010],cnte;struct edge{ int to,next;}e[10010];inline void add(int u,int v){ e[++cnte]=(edge){v,first[u]};first[u]=cnte;in[v]++;}int gcd(int x,int y){ if(y==0) return x; return gcd(y,x%y);}void dfs(int u){ vis[u]=1;int i; for(i=1;i<=n;i++){ if(!vis[i]&&!g[u][i]) add(u,i),dfs(i); }}struct gaygayquan{ int val,id;};inline bool operator <(gaygayquan x,gaygayquan b){ return x.val<b.val;}gaygayquan mp(int l,int r){ return (gaygayquan){l,r};}priority_queue<gaygayquan>q;int main(){ memset(first,-1,sizeof(first)); n=read();int i,j,v;gaygayquan gay; for(i=1;i<=n;i++) a[i]=read(); sort(a+1,a+n+1); for(i=1;i<=n;i++){ for(j=1;j<i;j++){ if(gcd(a[i],a[j])==1) g[i][j]=g[j][i]=1; } } for(i=1;i<=n;i++) if(!vis[i]) dfs(i); for(i=1;i<=n;i++) if(!in[i]) q.push(mp(a[i],i)); while(!q.empty()){ gay=q.top();q.pop(); printf("%d ",gay.val); for(i=first[gay.id];~i;i=e[i].next){ v=e[i].to;in[v]--; if(in[v]==0) q.push(mp(a[v],v)); } }}
[AGC010E] Rearranging [拓撲排序+堆]