[LuoguP1053][Noip2005]篝火晚会
[LuoguP1053][Noip2005]篝火晚会(Link)
现在你有一个排成一个圈的\(N\)大小的队列,一开始的顺序是\(\{1,2,3,4...N\}\),一共有\(N\)个要求,第\(i\)个要求包含两个数\(L[i]\)和\(R[i]\),表示\(i\)的左右两个点的编号要是\(L[i]\)和\(R[i]\)。现在你可以将原始队列进行操作,即选择几个点\(\{B_1, B_2...B_M\}\)个点,使之依次向右移动一个单位,而\(B_M\)移动到\(B_1\)位置。(\(B\)不一定连续)。每次的移动都需要花费\(M\)的代价。求最小代价使得满足所有要求。若不行则输出\(-1\)。
最开始我们要判断是不是要输出\(-1\),很显然如果将所有的要求连边(\(Link(i, L[i]) ; Link(i, R[i])\)),核发情况就会构成一个环。如果构不成环那么肯定不合法,就输出\(-1\)。那么我们要做的就是根据\(L[i]\)和\(R[i]\)进行一遍搜索,然后立个\(Vis[i]\),在搜索完之后我们进行一遍判断,如果所有的\(Vis[i]\)都等于\(1\),那么久合法,否则就不合法。
inline void Dfs(int Now) {
F[Now] = 1 ;
if (! F[L[Now]]) Dfs(L[Now]) ;
else if (! F[R[Now]]) Dfs(R[Now]) ;
else return ;
}
Dfs(1) ;
for (int i = 1 ; i <= N ; i ++) if (! F[i]) {
puts("-1") ; return 0 ;
}
判断合法之后我们再进行下面的东西。
首先发现这个环很难受于是我们把它变成链。
inline void Build_Chain(int Now) {
Line[++ Sum] = Now ; V[Now] = 1 ;
if (! V[L[Now]]) {
Build_Chain(L[Now]) ;
return ;
}
if (! V[R[Now]]) {
Build_Chain(R[Now]) ;
return ;
}
return ;
}
然后对于样例我们就建出来了一条\(\{1 ~4 ~2~ 3\}\)的链。
然后我们考虑最优的方案肯定是对于每一次的序列只操作与目标链的位置不相同的点。拿样例为例子。
\(\{1 ~4 ~2~ 3\}\)和\(\{1 ~2 ~3~ 4\}\)比,我们发现\(\{4, 2, 3\}\)的位置都不一样,于是操作\(\{4, 2, 3\}\),变为\(\{1 ~3 ~4 ~2\}\)。然后我们发现还是这三个数不一样,于是继续操作就变成了目标序列。
发现不大一样啊,然后我们发现这条链的建立顺序是先左后右的顺序,因此我们尝试再次建立一个先右后左的顺序的到的链就是\(\{1~3~2~4\}\),再次操作发现就得到了答案\(2\)。于是我们知道一条链的出的结果不一定最优,我们要建两条链。然后取答案的最优值。
因此我们可以看到答案的雏形就是对于每一次操作的新序列,如果有\(A\)个相同的单位点,也就是有\(N- A\)个不相同的,那么代价就是\(N - A\)。
然后可以进一步优化发现对于每一个元素,我们记录一下它和目标序列的差值为\(T[i]\),然后我们寻找所有的\(N\)个\(T[i]\),对于每一个相同\(T[i]\)的\(i\)来说它们是等价的,因为都可以通过\(T[i]\)次换到目标点。于是我们记录两条链的最大相同\(T[i]\)数,然后用\(N\)一减就是答案。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std ;
typedef long long LL ;
const int MAXN = 50100 ;
int N, Line[MAXN], Sum, Ans, V[MAXN], F[MAXN], L[MAXN], R[MAXN], Line2[MAXN], Sum2 ;
int T[MAXN] ;
inline int Read() {
int X = 0, F = 1 ; char ch = getchar() ;
while (ch > '9' || ch < '0') F = (ch == '-' ? - 1 : 1), ch = getchar() ;
while (ch >= '0' && ch <= '9') X=(X<<1)+(X<<3)+(ch^48), ch = getchar() ;
return X * F ;
}
inline void Dfs(int Now) {
F[Now] = 1 ;
if (! F[L[Now]]) Dfs(L[Now]) ;
else if (! F[R[Now]]) Dfs(R[Now]) ;
else return ;
}
inline void Build_Chain(int Now) {
Line[++ Sum] = Now ; V[Now] = 1 ;
if (! V[L[Now]]) {
Build_Chain(L[Now]) ;
return ;
}
if (! V[R[Now]]) {
Build_Chain(R[Now]) ;
return ;
}
return ;
}
inline void Build_Chain2(int Now) {
Line2[++ Sum2] = Now ; V[Now] = 1 ;
if (! V[R[Now]]) {
Build_Chain2(R[Now]) ;
return ;
}
if (! V[L[Now]]) {
Build_Chain2(L[Now]) ;
return ;
}
return ;
}
int main() {
N = Read() ;
for (int i = 1 ; i <= N ; i ++) {
int X = Read(), Y = Read() ;
L[i] = X ; R[i] = Y ;
}
Dfs(1) ;
for (int i = 1 ; i <= N ; i ++) if (! F[i]) {
puts("-1") ; return 0 ;
}
Build_Chain(1) ;
memset(V, 0, sizeof(V)) ;
Build_Chain2(1) ;
for (int i = 1 ; i <= N ; i ++) {
int K = Line[i] - i ;
K = (K + N) % N ;
T[K] ++ ;
}
for (int i = 1 ; i <= N ; i ++) Ans = max(Ans, T[i]) ;
memset(T, 0, sizeof(T)) ;
for (int i = 1 ; i <= N ; i ++) {
int K = Line2[i] - i ;
K = (K + N) % N ;
T[K] ++ ;
}
for (int i = 1 ; i <= N ; i ++) Ans = max(Ans, T[i]) ;
printf("%d", N - Ans) ;
return 0 ;
}
[LuoguP1053][Noip2005]篝火晚会的更多相关文章
- NOIP2005 篝火晚会 解题报告
佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小教官”.在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会.一共有n个同学,编号从1到n.一开始,同学们按照1,2,… ...
- NOIP2005 篝火晚会
篝火晚会 (fire.pas/c/cpp) [问题描述] 佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小教官”.在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会. ...
- Luogu1053 NOIP2005篝火晚会
首先造出所要求的得到的环.如果将位置一一对应上,答案就是不在所要求位置的人数.因为显然这是个下界,并且脑补一下能构造出方案达到这个下界. 剩下的问题是找到一种对应方案使错位数最少.可以暴力旋转这个环, ...
- noip2005篝火晚会
这是一道不算太难的题,但愚蠢的我并没有想到. 首先,判断无解的情况:他想相邻的不想与他相邻. 然后,构造出合法的数列,因为第一位左边有两种选择,且构造出的环不等价,所以要做两次. (这一点我并没有想清 ...
- 「NOIP2005」「Codevs1106」篝火晚会
题目描述 Description 佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小教官”.在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会.一共有n个同学,编号从1 ...
- [NOIP2005] 提高组 洛谷P1053 篝火晚会
题目描述 佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小教官”.在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会.一共有n个同学,编号从1到n.一开始,同学们按照 ...
- [NOIP 2005]-- 篝火晚会
额~~,对这组题感兴趣的具体的解题报告可以戳戳这里:http://wenku.baidu.com/view/878beb64783e0912a2162aa7.html?qq-pf-to=pcqq.c2 ...
- 洛谷 P1053 篝火晚会 解题报告
P1053 篝火晚会 题目描述 佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了"小教官".在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会.一共有 ...
- P1053 篝火晚会
题目描述 佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小教官”.在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会.一共有nnn个同学,编号从111到nnn.一开始 ...
随机推荐
- JSP总结摘要
一 概述 1.什么是JSP? Java Server Pages,服务器端负责页面展示的技术,可以嵌套java语言,以取代使用Servlet生成页面的方式,底层被转化为Servlet. 二 路径 1. ...
- 【转载】python实例手册
今天写爬虫的时候遇到了问题,在网上不停地查找资料,居然碰到两篇好文章: 1.python实例手册 作者:没头脑的土豆 另一篇在这:shell实例手册 python实例手册 #encoding:ut ...
- javascript实现数据结构: 树和森林
树的3种常用链表结构 1 双亲表示法(顺序存储结构) 优点:parent(tree, x)操作可以在常量时间内实现 缺点:求结点的孩子时需要遍历整个结构 用一组连续的存储空间来存储树的结点,同时在每个 ...
- Leetcode算法比赛----First Unique Character in a String
问题描述 Given a string, find the first non-repeating character in it and return it's index. If it doesn ...
- 第2课 android机器人的翻页相册
一.准备:准备像素大小相同的图片若干张.(本例中的图片,统一像素大小为310*310,请保存至本机电脑并按顺序命名为1.jpg至6.jpg) 二.启动与登陆: 启动谷歌浏览器,并在地址栏里输入loca ...
- .PHONY makefile中的伪目标
我的理解: 拿clean举例,如果make完成后,自己另外定义一个名叫clean的文件,再执行make clean时,将不会执行rm命令. 为了避免出现这个问题,需要.PHONY: clean === ...
- SpringMVC中使用DispatcherServlet
接触Web开发的时候我们会利用Servlet来接收和转发前端页面的各种请求,我们通常会在一个页面中对应一个Servlet来处理这个页面上和用户交互的信息,通常我门遇到5个以内的页面自己来写Servle ...
- 二、python小功能记录——监听鼠标事件
1.原文链接 #-*- coding:utf-8 -*- from pynput.mouse import Button, Controller ## ======================== ...
- Java学习---Java面试基础考核·
Java中sleep和wait的区别 ① 这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类. sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线 ...
- Apache的配置详解
Apache的配置由httpd.conf文件配置,因此下面的配置指令都是在httpd.conf文件中修改. 主站点的配置(基本配置) (1) 基本配置: ServerRoot "/mnt/s ...