题目描述
佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小教官”。在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会。一共有n个同学,编号从1到n。一开始,同学们按照1,2,……,n的顺序坐成一圈,而实际上每个人都有两个最希望相邻的同学。如何下命令调整同学的次序,形成新的一个圈,使之符合同学们的意愿,成为摆在佳佳面前的一大难题。
佳佳可向同学们下达命令,每一个命令的形式如下:
(b1, b2,... bm -1, bm)
这里m的值是由佳佳决定的,每次命令m的值都可以不同。这个命令的作用是移动编号是b1,b2,…… bm的这m个同学的位置。要求b1换到b2的位置上,b2换到b3的位置上,……,要求bm换到b1的位置上。执行每个命令都需要一些代价。我们假定如果一个命令要移动m个人的位置,那么这个命令的代价就是m。我们需要佳佳用最少的总代价实现同学们的意愿,你能帮助佳佳吗?
输入输出格式
输入格式:输入文件fire.in的第一行是一个整数n(3 <= n <= 50000),表示一共有n个同学。其后n行每行包括两个不同的正整数,以一个空格隔开,分别表示编号是1的同学最希望相邻的两个同学的编号,编号是2的同学最希望相邻的两个同学的编号,……,编号是n的同学最希望相邻的两个同学的编号。
输出格式:输出文件fire.out包括一行,这一行只包含一个整数,为最小的总代价。如果无论怎么调整都不能符合每个同学的愿望,则输出-1。
输入输出样例
输入样例#1:
4 3 4 4 3 1 2 1 2
输出样例#1:
2
说明
对于30%的数据,n <= 1000;
对于全部的数据,n <= 50000。
2005提高组第三题
#include<iostream> #include<cstdio> #include<cstring> #include<map> #define maxn 50010 using namespace std; map<string,bool>vis; map<string,bool>ok; int n,a[maxn],b[maxn],ans=0x7fffffff; void dfs(string now,int sum){ if(sum>=ans)return; if(sum>n)return; if(ok[now]){ ans=min(ans,sum); return; } string to=""; for(int len=2;len<=n;len++){ for(int l=0;l<=n-len;l++){ int r=l+len-1; to=""; to=to+now.substr(0,l); to=to+now[r]; to=to+now.substr(l,len-1); to=to+now.substr(r+1,n-r); if(vis[to])continue; dfs(to,sum+len); } } } int main(){ freopen("Cola.txt","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]); string s=""; //char ch=a[1]+'0'; s=s+'1'; s=s+(char)(a[1]+'0'); for(int i=2;i<n;i++){ int now=s[i-1]-'0'; if(s[i-2]==(char)(a[now]+'0'))s=s+(char)(b[now]+'0'); if(s[i-2]==(char)(b[now]+'0')) s=s+(char)(a[now]+'0'); } bool flag=0; if(s.length()!=n)flag=1; ok[s]=1; string ss=""; for(int i=1;i<n;i++){ ss=ss+s[n-1]; ss=ss+s.substr(0,3); ok[ss]=1; s=ss;ss=""; } s="1"; s=s+(char)(b[1]+'0'); for(int i=2;i<n;i++){ int now=s[i-1]-'0'; if(s[i-2]==(char)(a[now]+'0'))s=s+(char)(b[now]+'0'); if(s[i-2]==(char)(b[now]+'0')) s=s+(char)(a[now]+'0'); } if(s.length()==n)flag=0; ok[s]=1; ss=""; for(int i=1;i<n;i++){ ss=ss+s[n-1]; ss=ss+s.substr(0,3); ok[ss]=1; s=ss;ss=""; } if(flag){ puts("-1"); return 0; } string s1=""; for(int i=1;i<=n;i++)s1=s1+(char)(i+'0'); vis[s1]=1; dfs(s1,0); printf("%d",ans); }
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<queue> #include<algorithm> #define maxn 50010 using namespace std; int n,a[maxn],b[maxn],p[maxn],k,f[maxn],s,ans,l; bool vis[maxn]; int main(){ freopen("Cola.txt","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]); k=0;l=1; for(int i=b[1];i!=1&&vis[i]==0;){ p[++k]=l;vis[i]=1; if(a[i]==l){l=i;i=b[i];} else{l=i;i=a[i];} } p[++k]=l; if(k!=n){ puts("-1");return 0; } memset(f,0,sizeof(f)); for(int i=1;i<=n;i++){ if(p[i]>=i)f[p[i]-i]++; else f[p[i]+n-i]++; } for(int i=0;i<n;i++)ans=max(ans,f[i]); k=0;l=1; for(int i=a[1];i!=1;){ p[++k]=l; if(a[i]==l){l=i;i=b[i];} else{l=i;i=a[i];} } p[++k]=l; memset(f,0,sizeof(f)); for(int i=1;i<=n;i++){ if(p[i]>=i)f[p[i]-i]++; else f[p[i]+n-i]++; } for(int i=0;i<n;i++)ans=max(ans,f[i]); printf("%d",n-ans); }