小明组织活动的任务
时间限制:2000 ms | 内存限制:65535 KB
难度:6
描述 小明刚进高中,在军训的时候,由于小明吃苦耐劳,很快得到了教官的赏识,成为了“小教官”。在军训结束的那天晚上,小明被命令组织同学们进行篝火晚会。一共有n个同学,编号从1到n。一开始,同学们按照1,2,……,n的顺序坐成一圈,而实际上每个人都有两个最希望相邻的同学。如何下命令调整同学的次序,形成新的一个圈,使之符合同学们的意愿,成为摆在小明面前的一大难题。
小明可向同学们下达命令,每一个命令的形式如下:
(b1, b2,... bm -1, bm)
这里m的值是由小明决定的,每次命令m的值都可以不同。这个命令的作用是移动编号是b1,b2,…… bm –1,bm的这m个同学的位置。要求b1换到b2的位置上,b2换到b3的位置上,……,要求bm换到b1的位置上。
执行每个命令都需要一些代价。我们假定如果一个命令要移动m个人的位置,那么这个命令的代价就是m。我们需要小明用最少的总代价实现同学们的意愿,聪明的小明也有犯傻的时候,你能帮助小明吗?
n <= 50000。
输入第一行输入N(0
样例输入1
4
3 4
4 3
1 2
1 2
样例输出2
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
#define inf 1000000000
#define MOD 1000000007
#define maxn 51005
#define lowbit(x) (x&-x)
#define eps 1e-10
int a[maxn],b[maxn],c[maxn],t1[maxn],t2[maxn];
bool vis[maxn];
int main(void)
{
int T,i,ans,n;
scanf("%d",&T);
while(T--)
{
ans=0;bool flag=0;
memset(t1,0,sizeof(t1));
memset(t2,0,sizeof(t2));
memset(vis,0,sizeof(vis));
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d%d",&a[i],&b[i]);
c[1]=1;c[2]=a[1];
vis[c[1]]=vis[c[2]]=1;
for(i=2;i { if(c[i-1]==a[c[i]]) c[i+1]=b[c[i]]; else if(c[i-1]==b[c[i]]) c[i+1]=a[c[i]]; else { flag=1; break; } vis[c[i+1]]=1; } for(i=1;i<=n;i++) if(vis[i]==0) flag=1; if(flag) { printf("-1\n"); continue; } for(i=1;i<=n;i++) { int d=(c[i]-i+n)%n; t1[d]++; ans=max(ans,t1[d]); d=(c[n-i+1]-i+n)%n; t2[d]++; ans=max(ans,t2[d]); } printf("%d\n",n-ans); } return 0; } #include #include #include using namespace std; #define M 50005 int en[M],res; //en[]最终目标序列,res是en合法标记 int need[M][3];//各个需求 [][0]标记该人是否入列,[][1],[][2]为左右需求 int searchSame[M];//置换群求相同位置时使用 //判断数据是否能够满足要求 void judge(int n) { en[1]=1; for (int i=2;i<=n;i++) { if(need[ need[en[i-1]][1] ][0]==0) { en[i]=need[en[i-1]][1]; need[en[i-1]][0]=1; } else if(need[ need[en[i-1]][2] ][0]==0) { en[i]=need[en[i-1]][2]; need[en[i-1]][0]=1; } } else {res=-1; return;} } if( (need[en[n]][1]==en[1] || need[en[n]][1]==en[n-1])&& (need[en[n]][2]==en[1] || need[en[n]][2]==en[n-1]) ) return; else res=-1; } //计算需求数列与原数列对比,无需移位的个数的最大值eqmax int calculation(int n) { int eqmax=0; int temp; /*for (int i=1;i<=n;i++) { temp=0; for (int j=1;j<=n;j++) { if(en[(i+j-2)%n+1]==sta[j]) temp++; } if(eqmax }*/ memset(searchSame,0,sizeof(searchSame)); temp=0; for (int i=1;i<=n;i++) { temp=(n+en[i]-i)%n; searchSame[temp]++; } for (int i=0;i<=n;i++) if(eqmax //以下部分为上述代码的镜像操作 memset(searchSame,0,sizeof(searchSame)); for (int i=1;i<=n;i++) { temp=(n+en[n-i+1]-i)%n; searchSame[temp]++; } for(int i=0;i<=n;i++) if(eqmax return n-eqmax; } int main() { //freopen("1.txt","r",stdin); int N,n; scanf("%d",&N); while(N--) { memset(need,0,sizeof(need)); memset(en,0,sizeof(en)); res=0; scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d%d",&need[i][1],&need[i][2]); } judge(n); if(res!=-1) printf("%d\n",calculation(n)); else printf("-1\n"); } return 0; }