我是靠谱客的博主 辛勤白羊,最近开发中收集的这篇文章主要介绍AGC010E - Rearranging,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

中文题意:
Hellen首先按照自己的意愿将n个数重新排列(可以是原来的顺序),然后她让Shawn进行如下操作:选择一对相邻且互质的数,交换它们的位置.(这个操作Shawn可以进行无数次.)
Hellen想要这个序列的字典序尽可能小,而Shawn想要这个序列的字典序尽可能大.Hellen想让你告诉她在两人都采取最优策略的情况下,最后形成的序列是什么样子的.

题解:
这个题考试的时候居然没有想出来,其实很简单,我们可以很简单的发现,如果两个数的gcd=不为1,那么这两个数的相对位置是无法改变的,基于这一点,我们可以把相对位置无法改变的数连边,然后跑拓扑序,由于前面的人要使字典序尽可能小,我们可以开始把较小的卡在前面,之后为了尽量不让第2个人把后面更大的抓过来,我们跑dfs把它能影响的数放置在后面。之后跑一遍拓扑就OK了。

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int MAXN=2005;
int n,a[MAXN];
int rd[MAXN];
int vis[MAXN];
struct edge
{
	int v,nxt;
	edge(){}
	edge(int vv,int nn)
	{
		v=vv,nxt=nn;
	}
}E[MAXN*MAXN];
int w[MAXN],ncnt=0;
struct node
{
	int id,val;
	node(){}
	node(int ii,int vv)
	{
		id=ii,val=vv;
	}
	bool operator < (const node &a)const 
	{
		return a.val>val;
	}
};
priority_queue<node>q;
int gcd(int a,int b)
{
	return b==0?a:gcd(b,a%b);
}
void addedge(int u,int v)
{
	ncnt++;
	E[ncnt]=edge(v,w[u]);
	w[u]=ncnt;
}
void dfs(int u)
{
	vis[u]=1;
	for(int i=1;i<=n;i++)
	{
		if(!vis[i]&&gcd(a[u],a[i])!=1)
		{
			dfs(i);
			rd[i]++;
			addedge(u,i);
		}
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++)
		if(!vis[i])
			dfs(i);
	for(int i=1;i<=n;i++)
		if(rd[i]==0)
			q.push(node(i,a[i]));
	while(!q.empty())
	{
		node k=q.top();
		q.pop();
		printf("%d ",k.val);
		for(int i=w[k.id];i;i=E[i].nxt)
		{
			int v=E[i].v;
			rd[v]--;
			if(rd[v]==0)
				q.push(node(v,a[v]));
		}
	}
}

最后

以上就是辛勤白羊为你收集整理的AGC010E - Rearranging的全部内容,希望文章能够帮你解决AGC010E - Rearranging所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(62)

评论列表共有 0 条评论

立即
投稿
返回
顶部