題目描述
佳佳剛進高中,在軍訓的時候,由於佳佳吃苦耐勞,很快得到了教官的賞識,成爲了“小教官”。在軍訓結束的那天晚上,佳佳被命令組織同學們進行篝火晚會。一共有個同學,編號從到。一開始,同學們按照的順序坐成一圈,而實際上每個人都有兩個最希望相鄰的同學。如何下命令調整同學的次序,形成新的一個圈,使之符合同學們的意願,成爲擺在佳佳面前的一大難題。
佳佳可向同學們下達命令,每一個命令的形式如下:
這裏的值是由佳佳決定的,每次命令的值都可以不同。這個命令的作用是移動編號是的這個同學的位置。要求換到的位置上,換到的位置上,……,要求換到的位置上。執行每個命令都需要一些代價。我們假定如果一個命令要移動個人的位置,那麼這個命令的代價就是。我們需要佳佳用最少的總代價實現同學們的意願,你能幫助佳佳嗎?
輸入格式
第一行是一個整數,表示一共有個同學。
其後行每行包括個不同的正整數,以一個空格隔開,分別表示編號是的同學最希望相鄰的兩個同學的編號,編號是的同學最希望相鄰的兩個同學的編號,……,編號是的同學最希望相鄰的兩個同學的編號。
輸出格式
一個整數,爲最小的總代價。如果無論怎麼調整都不能符合每個同學的願望,則輸出。
輸入輸出樣例
輸入 #1 複製
4
3 4
4 3
1 2
1 2
輸出 #1 複製
2
說明/提示
對於的數據,;
對於全部的數據,。
提高組第三題
思路
首先,爲了讓總代價最少,一定就要讓移動的人次最少,我們方法就是找到一組儘可能多的不用移動的,而剩下的一坨,有可能是一次換的,有可能是兩次……但是,無論是多少次,最少的代價一定就是總個數,因爲每個人只需要換一次就可以到達他的位置,連成一個環,如果還有其他的環,就再每人換一次,又成一個環,知道換完位置。這樣每個人就只需要移動一次就夠了。
那麼,問題就轉換成了求最多可以有多少個人不用動。
所以,我就打了一個模擬,直接從頭到尾看看有多少不用動,結果,聽取聲一片。
額,我再乍一看,一個是初始環,另一個是目標環,要找到最多能有多少一樣的,應該要一次一次對過去,然後,有一個方法,就是求出他要移動多少格纔可以到達最後的目標點。
這樣,移動格數相同的就一定是同一組的,也就是同一次移動的,然後找到最多的一組就可以了。
結果代碼一交,又是
然後又細細一想,啊,目標環還有可能是另一個方向擺的,就是比如說樣例,可能是1 3 2 4
,也有可能是1 4 2 3
,所以就要兩次。
結果交上去,終於了(太不容易了)
代碼
#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define maxn 50001
using namespace std;
int n;
int a[maxn],b[maxn];//每個點的兩邊的點
bool flag[maxn];//判斷是否已經用過了
int k[maxn],f[maxn];//目標序列,距離目標點有多少距離
int sum[maxn];//桶計數
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]);
int now=1;
k[1]=1;
flag[now]=1;
for(int i=2;i<=n;i++){
if(!flag[a[now]]){//左邊的點還沒有用過
k[i]=a[now];
now=a[now];
flag[now]=1;
}
else if(!flag[b[now]]){//右邊的點還沒用過
k[i]=b[now];
now=b[now];
flag[now]=1;
}
else{//兩邊的點都用過了,判無解
printf("-1");
return 0;
}
}
for(int i=1;i<=n;i++)f[i]=(i-k[i]+n)%n;//求距離
int maxx=0;
for(int i=1;i<=n;i++){
sum[f[i]]++;//桶計數
maxx=max(maxx,sum[f[i]]);//求最大值
}
//重來一遍
memset(sum,0,sizeof(sum));//清空
memset(flag,0,sizeof(flag));//清空
now=1;
k[1]=1;
flag[now]=1;
for(int i=2;i<=n;i++){
if(!flag[b[now]]){//反過來就可以求另一種順序了
k[i]=b[now];
now=b[now];
flag[now]=1;
}
else if(!flag[a[now]]){
k[i]=a[now];
now=a[now];
flag[now]=1;
}
}
for(int i=1;i<=n;i++)f[i]=(i-k[i]+n)%n;
for(int i=1;i<=n;i++){
sum[f[i]]++;
maxx=max(maxx,sum[f[i]]);
}
printf("%d",n-maxx);//注意最後要用來減
return 0;
}