【题解】 [NOI2009]变换序列 (二分图匹配)

懒得复制,戳我戳我

Solution:

  • 这个题面出的很毒瘤,读懂了其实是个板子题qwq
  • 题面意思:有个\(0\)至\(N-1\)的数列是由另一个数列通过加减得到的,相当于将\(A_i\)变成\(i\),每一步的代价计算就是\(min(A_i-i,N-(A_i-i))\),并且\(A_i\left(0<=i<N\right)\)互不相同,读入代价,要求字典序最小的满足要求的数列
  • 我们设读入的为\(w[i]\)
  • 思路其实很简单,\(i\)只可能是由\(i-w[i]\) 或者 \(i+w[i]\) 或者 \(i+N-w[i]\) 或者 \(i-N+w[i]\),然后我们把符合范围\(0\)至\(N-1\)的对应点从大到小建图,这样可以保证搜的时候是从小的点开始
  • 然后就从\(N-1\)到\(0\)进行二分图匹配,如果无法匹配就输出\(No Answer\),这样从后到前匈牙利算法去做,保证越前面的匹配的数是最小的。
  • 因为\(be[i]\)中存的是\(i\)数字对应变成的数字是什么,所以反过来存一下输出就好啦

    主要是想字典序最小的地方有点emmm神奇,其他的地方还是比较显然的


Code:

//It is coded by Ning_Mew on 3.17
#include<bits/stdc++.h>

using namespace std;

const int maxn=1e5+7;

bool vis[maxn];
int n,w[maxn],be[maxn],ans[maxn];
int head[maxn],cnt=0;
struct Edge{
  int nxt,to;
}edge[maxn*4];
priority_queue<int>q;

void add(int from,int to){
  edge[++cnt].nxt=head[from];
  edge[cnt].to=to;
  head[from]=cnt;
}
bool find(int k){
  for(int i=head[k];i!=0;i=edge[i].nxt){
    int v=edge[i].to;
    if(!vis[v]){
      vis[v]=true;
      if(be[v]==-1||find(be[v])){be[v]=k;return true;}
    }
  }return false;
}
int main(){
  scanf("%d",&n);
  while(!q.empty())q.pop();
  for(int i=0;i<n;i++){
    scanf("%d",&w[i]);
    q.push(i-w[i]);  q.push(i+w[i]);
    q.push(i+n-w[i]);q.push(i-n+w[i]);
    while(!q.empty()){
      int box=q.top();q.pop();
      //cout<<box<<endl;
      if(box>=0&&box<n)add(i,box);//cout<<i<<‘ ‘<<box<<endl;
    }
  }
  memset(be,-1,sizeof(be));
  for(int i=n-1;i>=0;i--){
    memset(vis,false,sizeof(vis));
    if(find(i));
    else{printf("No Answer\n");return 0;}
  }
  for(int i=0;i<n;i++)ans[be[i]]=i;
  for(int i=0;i<n;i++)printf("%d ",ans[i]);printf("\n");
  return 0;
}

原文地址:https://www.cnblogs.com/Ning-Mew/p/8590580.html

时间: 2024-07-30 05:52:56

【题解】 [NOI2009]变换序列 (二分图匹配)的相关文章

【BZOJ1562】【jzyzOJ1730】【COGS409】NOI2009变换序列 二分图匹配

[问题描述] 对于N个整数0, 1, --, N-1,一个变换序列T可以将i变成Ti,其中 定义x和y之间的距离.给定每个i和Ti之间的距离D(i,Ti), 你需要求出一个满足要求的变换序列T.如果有多个满足条件的序列,输出其中字典序最小的一个. 说明:对于两个变换序列S和T,如果存在p<N,满足对于i=0,1,--p-1,Si=Ti且Sp<Tp,我们称S比T字典序小. [输入文件] 输入文件transform.in的第一行包含一个整数N,表示序列的长度.接下来的一行包含N个整数Di,其中Di

Bzoj 1562: [NOI2009]变换序列 匈牙利算法,二分图匹配

题目: http://cojs.tk/cogs/problem/problem.php?pid=409 409. [NOI2009]变换序列 ★★☆   输入文件:transform.in   输出文件:transform.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 对于N个整数0, 1, ……, N-1,一个变换序列T可以将i变成Ti,其中 定义x和y之间的距离.给定每个i和Ti之间的距离D(i,Ti), 你需要求出一个满足要求的变换序列T.如果有多个满足条

noi2009变换序列

noi2009变换序列 一.题目 1843 变换序列 2009年NOI全国竞赛 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description 对于N个整数0,1,…,N-1,一个变换序列T可以将i变成Ti,其中:Ti∈{0,1,…,N-1}且Ui=1 to n-1 {Ti}={0,1,…,N-1}.任意x,y∈{0,1,…,N-1},定义x和y之间的距离D(x,y)=min{|x-y|,N-|x-y|}.给定每个i和Ti之间的距离D

BZOJ1562: [NOI2009]变换序列

1562: [NOI2009]变换序列 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1148  Solved: 599[Submit][Status] Description Input Output Sample Input 5 1 1 2 2 1 Sample Output 1 2 4 0 3 HINT 30%的数据中N≤50:60%的数据中N≤500:100%的数据中N≤10000. Source 题解: 不愧是NOI的题目,果然是好题. 具

【bzoj1562】 NOI2009—变换序列

http://www.lydsy.com/JudgeOnline/problem.php?id=1562 (题目链接) 题意:给出一个序列(0~n-1),这个序列经过某个变换会成为另外一个序列,但是其中的元素不会改变,给出初始序列与变换后的序列每一位上的“距离”,求字典序最小的变换序列. Solution  每个位置上只有2种情况,很明显的二分图匹配.因为要求字典序最小,我们考虑匈牙利算法的运行方式,是保证当前匹配的点最优,所以连边是将字典序小的点尽可能后连,保证第一个邻接表第一个选出来的点事字

1562: [NOI2009]变换序列 - BZOJ

Description Input Output Sample Input 5 1 1 2 2 1 Sample Output 1 2 4 0 3 HINT 30%的数据中N≤50:60%的数据中N≤500:100%的数据中N≤10000. 二分图匹配,倒着匹配,每次选小的增广(随便乱yy一下,应该就可以证明是字典序最小的吧) 1 const 2 maxn=10010; 3 var 4 first,link:array[0..maxn]of longint; 5 a:array[0..maxn,

BZOJ 1562 [NOI2009]变换序列:二分图匹配

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1562 题意: 给定n,定义D(x,y) =  min(|x-y|, n-|x-y|),然后给定数组d[i] = D(i,T[i]). 让你求一个0到n-1的排列T,下标i∈[0,n-1],满足给定的D(i,T[i]),且字典序最小. 若没有答案输出"No Answer". 题解: 其实就是让你求一个排列T,其中T[i]要么填(i+d[i])%n,要么填(i-d[i]+n)%n.

[luoguP1963] [NOI2009]变换序列(二分图最大匹配)

传送门 根据公式xjb推一下,然后就可以连边. 考虑到字典序最小,和匈牙利算法的实现过程,要倒序匹配. #include <cmath> #include <cstdio> #include <vector> #include <cstring> #include <iostream> #include <algorithm> #define N 40001 using namespace std; int n, cnt; int h

【题解】CF739D Recover a functional graph(构造+二分图匹配)

[题解]CF739D Recover a functional graph(构造+二分图匹配) 题目大意 一个图被称为F图当且仅当每个点出度为1.可以发现这个图是一个内向基环森林,给出所有点到它能到达的环(只会有一个)的距离dis和那个环的长度len,然而有些点的信息模糊了,用?代替,可以是任何数.现在你要输出一个合法的构造方案. 可以提炼出一个图是F图的条件: 对应环的距离数组是自然数数列 \(len=k\)的点的个数是\(tk,t\in N^+\) 由于第二个条件只能用问号补,没有决策需要做