[Noip2005] 篝火晚会
题目描述
佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小教官”。在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会。一共有nnn个同学,编号从111到nnn。一开始,同学们按照1,2,…,n1,2,…,n1,2,…,n的顺序坐成一圈,而实际上每个人都有两个最希望相邻的同学。如何下命令调整同学的次序,形成新的一个圈,使之符合同学们的意愿,成为摆在佳佳面前的一大难题。
佳佳可向同学们下达命令,每一个命令的形式如下:
(b1,b2,...bm−1,bm)(b_1, b_2,... b_{m-1}, b_m)(b1,b2,...bm−1,bm)
这里mmm的值是由佳佳决定的,每次命令mmm的值都可以不同。这个命令的作用是移动编号是b1,b2,…,bmb_1,b_2,…, b_mb1,b2,…,bm的这m个同学的位置。要求b1b_1b1换到b2b_2b2的位置上,b2b_2b2换到b3b_3b3的位置上,……,要求bmb_mbm换到b1b_1b1的位置上。执行每个命令都需要一些代价。我们假定如果一个命令要移动mmm个人的位置,那么这个命令的代价就是mmm。我们需要佳佳用最少的总代价实现同学们的意愿,你能帮助佳佳吗?
输入输出格式
输入格式:第一行是一个整数n(3≤n≤50000)n(3 \le n \le 50000)n(3≤n≤50000),表示一共有nnn个同学。
其后nnn行每行包括222个不同的正整数,以一个空格隔开,分别表示编号是111的同学最希望相邻的两个同学的编号,编号是222的同学最希望相邻的两个同学的编号,……,编号是nnn的同学最希望相邻的两个同学的编号。
输出格式:一个整数,为最小的总代价。如果无论怎么调整都不能符合每个同学的愿望,则输出−1-1−1。
输入输出样例
说明
对于30%的数据,n≤1000n \le 1000n≤1000;
对于全部的数据,n≤50000n \le 50000n≤50000。
2005提高组第三题
#include <iostream> #include <cstdio> #include <queue> using namespace std; #define reg register inline int read() { int res = 0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48), ch=getchar(); return res; } #define N 50005 int n; int deg[N], ch[N][2]; int L[N], R[N]; int cnt[2][N]; int a[N]; int main() { n = read(); for (reg int i = 1 ; i <= n ; i ++) { ch[i][0] = read(), ch[i][1] = read(); deg[ch[i][0]]++, deg[ch[i][1]]++; } for (reg int i = 1 ; i <= n ; i ++) if (deg[i] != 2) return puts("-1"), 0; int p = 1, num = 0; L[1] = ch[1][0], R[1] = ch[1][1]; do { int y = R[p]; L[y] = p, R[y] = ch[y][0] == p ? ch[y][1] : ch[y][0]; p = y; num++; }while(p != 1); if (num != n) return puts("-1"), 0; p = 1; for (reg int i = 1 ; i <= n ; i ++, p = R[p]) cnt[0][(i-p+n)%n]++; p = 1; for (reg int i = 1 ; i <= n ; i ++, p = L[p]) cnt[1][(i-p+n)%n]++; int ans = 0; for (reg int i = 0 ; i < n ; i ++) ans = max(ans, max(cnt[0][i], cnt[1][i])); printf("%d\n", n - ans); return 0; }