题解 P1053 【篝火晚会】
-
NOIP2005提高组第 3 题
题面
https://www.luogu.org/problemnew/show/P1053 。
题目描述
佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小教官”。在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会。一共有
佳佳可向同学们下达命令,每一个命令的形式如下:
这里
输入输出格式
- 输入格式
第一行是一个整数
其后
- 输出格式
一个整数,为最小的总代价。如果无论怎么调整都不能符合每个同学的愿望,则输出
-1。
输入输出样例
- 输入样例#1
4 3 4 4 3 1 2 1 2 - 输出样例#1
2
数据范围
对于
对于全部的数据,
题解
首先我们可以通过给出来的相邻关系把这个环给建出来。
怎么建呢?首先先设
然后如果
反之,如果
如果都不满足的话说明这样的环不存在,输出
这一部分的代码是这样的:
a[n]=l[1],a[1]=1,a[2]=r[1];
for(int i=3;i<=n-1;i++)
{
if(a[i-2]==l[a[i-1]])
{
a[i]=r[a[i-1]];
}
else if(a[i-2]==r[a[i-1]])
{
a[i]=l[a[i-1]];
}
else
{
printf("-1");
return 0;
}
}
然后就是求答案辣!
我们用
并且用
易得,对于一个人
下面是这一部分的代码。
for(int i=1;i<=n;i++)
{
dis1[(i-a[i]+n)%n]++;
dis2[(i+a[i]+n)%n]++;
}
因为若有
求一下就可以了。
完整代码:
#include <cstdio>
int l[1000001],r[1000001];
int a[1000001],cx[1000001];
int dis1[1000001],dis2[1000001];
int max(int x,int y)
{
return x>y?x:y;
}
int main()
{
int n=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d %d",&l[i],&r[i]);
}
a[n]=l[1],a[1]=1,a[2]=r[1];
for(int i=3;i<=n-1;i++)
{
if(a[i-2]==l[a[i-1]])
{
a[i]=r[a[i-1]];
}
else if(a[i-2]==r[a[i-1]])
{
a[i]=l[a[i-1]];
}
else
{
printf("-1");
return 0;
}
}
for(int i=1;i<=n;i++)
{
dis1[(i-a[i]+n)%n]++;
dis2[(a[i]+i+n)%n]++;
}
int ans=0;
for(int i=0;i<=n*2;i++)
{
ans=max(ans,max(dis1[i],dis2[i]));
}
printf("%d",n-ans);
return 0;
}