[Luogu 1963] NOI2009 变换序列
[Luogu 1963] NOI2009 变换序列
什么?二分图匹配?这个确定可以建图?
「没有建不成图的图论题,只有你想不出的建模方法。」
建图相当玄学,不过理解大约也那么奇怪。
题里面对D(x,y)的定义那一长句,一开始没看明白,但实际会发现是一个环,而对于每一个点u,符合给定距离的点都有且只有2个(v1 && v2),连u->v1 && u->v2。
对于链式前向星选手,连边的时候注意先连终点序号大的,这样才能保证遍历时从小到大。
为什么要做这个操作呢?因为要求输出字典序最小的解,就必须保证较小的点优先匹配较小的点。
匈牙利算法的过程,总是通过调整先前匹配的点,而使当前点尽量不动。
所以,匈牙利算法倒序跑,增广时优先选小的点,这样就能够保证「越小的点越能匹配较小的点」,从而实现字典序最小化。(贪心思想)
最终输出X部每个点的匹配点即可。
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN=20010,MAXM=20010;
bool vis[MAXN];
int n,cnt,ans,head[MAXN],match[MAXN];
struct edge
{
int nxt,to;
}e[MAXM];
int Solve(int x)
{
if(x<0)
x+=n;
if(x>=n)
x-=n;
return x+n;
}
void AddEdge(int u,int v)
{
e[++cnt].nxt=head[u],e[cnt].to=v,head[u]=cnt;
}
void AddEdges(int u,int x)
{
int v1=Solve(u+x),v2=Solve(u-x);
if(v1<v2)
swap(v1,v2);
AddEdge(u,v1),AddEdge(u,v2);
}
bool DFS(int u)
{
for(int i=head[u],v;i;i=e[i].nxt)
if(!vis[v=e[i].to])
{
vis[v]=1;
if(!match[v] || DFS(match[v]))
{
match[u]=v,match[v]=u;
return 1;
}
}
return 0;
}
bool Hungary(void)
{
for(int i=n-1;i>=0;--i)
if(!match[i])
{
memset(vis,0,sizeof vis);
ans+=DFS(i);
}
return n==ans;
}
int main(int argc,char *argv[])
{
scanf("%d",&n);
for(int i=0,x;i<n;++i)
{
scanf("%d",&x);
AddEdges(i,x);
}
if(Hungary())
for(int i=0;i<n;++i)
printf("%d ",match[i]-n);
else
printf("No Answer");
putchar('\n');
return 0;
}
谢谢阅读
[Luogu 1963] NOI2009 变换序列的更多相关文章
- Luogu P1963 [NOI2009]变换序列(二分图匹配)
P1963 [NOI2009]变换序列 题意 题目描述 对于\(N\)个整数\(0,1, \cdots ,N-1\),一个变换序列\(T\)可以将\(i\)变成\(T_i\),其中\(T_i \in ...
- Bzoj 1562: [NOI2009]变换序列 匈牙利算法,二分图匹配
题目: http://cojs.tk/cogs/problem/problem.php?pid=409 409. [NOI2009]变换序列 ★★☆ 输入文件:transform.in 输出文 ...
- BZOJ 1562 [NOI2009] 变换序列
[NOI2009] 变换序列 [题解] 就是有一个序列,每个位置可以填两个数,不可重复,问最小字典序. 显然,可以建一个二分图,判合法就是找完美匹配. 那怎么弄最小字典序呢?有好多种解法,我这里给出了 ...
- noi2009变换序列
noi2009变换序列 一.题目 1843 变换序列 2009年NOI全国竞赛 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 ...
- 【bzoj1562】 NOI2009—变换序列
http://www.lydsy.com/JudgeOnline/problem.php?id=1562 (题目链接) 题意 给出一个序列(0~n-1),这个序列经过某个变换会成为另外一个序列,但是其 ...
- bzoj1562[NOI2009]变换序列——2016——3——12
任意门:http://www.lydsy.com/JudgeOnline/problem.php?id=1562 题目: 对于0,1,…,N-1的N个整数,给定一个距离序列D0,D1,…,DN-1,定 ...
- P1963 [NOI2009]变换序列
对于\(N\)个整数\(0, 1, \cdots, N-1,\)一个变换序列\(T\)可以将\(i\)变成\(T_i\),其中 \(T_i \in \{ 0,1,\cdots, N-1\}\)且 \( ...
- 【BZOJ1562】【jzyzOJ1730】【COGS409】NOI2009变换序列 二分图匹配
[问题描述] 对于N个整数0, 1, ……, N-1,一个变换序列T可以将i变成Ti,其中 定义x和y之间的距离.给定每个i和Ti之间的距离D(i,Ti), 你需要求出一个满足要求的变换 ...
- BZOJ1562: [NOI2009]变换序列(二分图 匈牙利)
Description Input Output Sample Input 5 1 1 2 2 1 Sample Output 1 2 4 0 3 HINT 30%的数据中N≤50:60%的数据中N≤ ...
随机推荐
- ZOJ 3686 A Simple Tree Problem(线段树)
Description Given a rooted tree, each node has a boolean (0 or 1) labeled on it. Initially, all the ...
- 关于LNMP常见问题和性能方面的个人理解
简单整理,自己做备忘的,不为其他作任何参考- PHP程序 1.开启慢日志,过滤超时时间为1s的方法,针对性优化,可以通过添加缓存方式解决. 2.过滤access日志,统计哪些请求较多较为频繁,是否合理 ...
- PCA算法理解及代码实现
github:PCA代码实现.PCA应用 本文算法均使用python3实现 1. 数据降维 在实际生产生活中,我们所获得的数据集在特征上往往具有很高的维度,对高维度的数据进行处理时消耗的时间很大, ...
- LintCode-56.两数之和
两数之和 给一个整数数组,找到两个数使得他们的和等于一个给定的数 target. 你需要实现的函数twoSum需要返回这两个数的下标, 并且第一个下标小于第二个下标.注意这里下标的范围是 1 到 n, ...
- 【alpha】Scrum站立会议第2次....10.17
小组名称:nice! 小组成员:李权 于淼 杨柳 刘芳芳 项目内容:约跑app 1.任务进度 成员 已完成 今日完成 李权 数据库设计 消息发送代码实现 于淼 注册.登录界面,以及登录界面后台代码.发 ...
- java 基本--数据类型转换--001
小可转大,大转小可能会损失精度(编译出错,需要强制转换)A: byte,short,char -> int -> long -> float ->doubleB: byte,s ...
- /proc/meminfo中meminfo的计算方法
/proc/meminfo里的可使用内存的计算没有那么简单,并不是简单的free和page cache的加和 free + pagecache 以此为基准 但是需要减去一些内存:首先要减去系统预留的内 ...
- 【bzoj1742】[Usaco2005 nov]Grazing on the Run 边跑边吃草 区间dp
题目描述 John养了一只叫Joseph的奶牛.一次她去放牛,来到一个非常长的一片地,上面有N块地方长了茂盛的草.我们可以认为草地是一个数轴上的一些点.Joseph看到这些草非常兴奋,它想把它们全部吃 ...
- BZOJ4700 适者(贪心+cdq分治+斜率优化)
首先考虑怎么安排攻击顺序.显然如果攻击了某台兵器就应该一直连续攻击直到将其破坏,破坏所需时间可以直接算出来,设其为b.假设确定了某个破坏顺序,如果交换相邻两个兵器,显然不会对其他兵器造成影响,两种顺序 ...
- 【题解】CF#1012 C-Hill
感觉这题的状态还是比较明显的.设置状态 \(f[i][j][0/1]\) 表示dp到第 \(i\) 个位置,前面(包括这里)已经出现了 \(j\) 个山峰,当前位置是不是山峰即可 dp.这样的状态有一 ...