[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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM