[NOIP2005] 篝火晚会
其实这个题目描述有点锅啊qwq
看了题解之后才明白过来原来编号没有要求连续qwq(但是题目中描述的那么规则到底是要怎样啊)
所以说这样题目就稍微简单了,要求的是初始环经过多少次变换成为符合条件的目标环。
那么首先我们需要先构建出来目标环。但是环不好处理,我们需要断环为链。但是断环为链显然是有两种情况,所以我们需要构建两个链。
eg.比如说样例的两种链情况:
1、2、4、3
1、3、2、1
然后有个结论就是:
遵循上述规律,使初始环变成期望环的代价是n-k(n是总数,k是在当前环和期望环中位置相同的数的个数)
构建完链之后按照上述规律来个check就可以了。
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#define MAXN 60010
using namespace std;
int n,ans;
int l[MAXN],r[MAXN],sum[MAXN],done[MAXN],s[MAXN];
inline void quit()
{
printf("-1\n");
exit(0);
}
inline int check()
{
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++)
sum[(s[i]-i+n)%n]++;
int maxx=0;
for(int i=0;i<=n;i++)
maxx=max(maxx,sum[i]);
return n-maxx;
}
inline int solve1()
{
memset(done,0,sizeof(done));
memset(s,0,sizeof(s));
s[1]=1; done[s[1]]=1;
s[2]=l[s[1]]; done[s[2]]=1;
for(int i=2;i<n;i++)
{
if(l[s[i]]==s[i-1]) s[i+1]=r[s[i]],done[s[i+1]]=1;
else if(r[s[i]]==s[i-1]) s[i+1]=l[s[i]],done[s[i+1]]=1;
}
for(int i=1;i<=n;i++)
if(!done[i])
quit();
return check();
}
inline int solve2()
{
memset(done,0,sizeof(done));
memset(s,0,sizeof(s));
s[1]=1; done[s[1]]=1;
s[2]=r[s[1]]; done[s[2]]=1;
for(int i=2;i<n;i++)
{
if(l[s[i]]==s[i-1]) s[i+1]=r[s[i]],done[s[i+1]]=1;
else if(r[s[i]]==s[i-1]) s[i+1]=l[s[i]],done[s[i+1]]=1;
}
for(int i=1;i<=n;i++)
if(!done[i])
quit();
return check();
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&l[i],&r[i]);
printf("%d\n",min(solve1(),solve2()));
return 0;
}