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

【问题描述】

对于N个整数0, 1, ……, N-1,一个变换序列T可以将i变成Ti,其中

定义xy之间的距离。给定每个iTi之间的距离D(i,Ti),

你需要求出一个满足要求的变换序列T。如果有多个满足条件的序列,输出其中字典序最小的一个。

说明:对于两个变换序列ST,如果存在p<N,满足对于i=0,1,……p-1,Si=TiSp<Tp,我们称ST字典序小。

【输入文件】

输入文件transform.in的第一行包含一个整数N,表示序列的长度。接下来的一行包含N个整数Di,其中Di表示iTi之间的距离。

【输出文件】

输出文件为transform.out。

如果至少存在一个满足要求的变换序列T,则输出文件中包含一行N个整数,表示你计算得到的字典序最小的T;否则输出”No Answer”(不含引号)。注意:输出文件中相邻两个数之间用一个空格分开,行末不包含多余空格。

【输入样例】

5

1 1 2 2 1

【输出样例】

1 2 4 0 3

倒序二分图匹配,使用vector容器省空间省时间。

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
int n;
int dis[10005];
int lin[10005];
int ans[10005];
bool f[10005];
vector<int>a[10005];

int flag(int q,int p)
{
    return min(abs(q-p),n-abs(q-p));
}

bool dfs(int x)
{
    int l=a[x].size();
    for(int i=0;i<l;++i)
    {
        if(!f[a[x][i]])
        {
            f[a[x][i]]=1;
            if(lin[a[x][i]]==-1||dfs(lin[a[x][i]]))
            {
                lin[a[x][i]]=x;
                return true;
            }
        }
    }
    return false;
}

int main()
{
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    //freopen("transform.in","r",stdin);
    //freopen("transform.out","w",stdout);
    memset(a,0,sizeof(a));
    cin>>n;
    for(int i=0;i<n;++i)
        scanf("%d",&dis[i]);
    for(int i=0;i<n;++i)
    {
        int x=i+dis[i];
        int y=i+n-dis[i];
        x%=n;y%=n;
        if(flag(x,i)!=dis[i]) x=-1;
        if(flag(y,i)!=dis[i]) y=-1;
        if(x>y) swap(x,y);
        if(x!=-1) a[i].push_back(x);
        if(y!=-1) a[i].push_back(y);
    }

    memset(lin,-1,sizeof(lin));
    for(int i=n-1;i>=0;--i)
    {
        memset(f,0,sizeof(f));
        if(!dfs(i))
        {
            cout<<"No Answer"<<endl;
            return 0;
        }
    }

    //cout<<123456<<endl;
    for(int i=0;i<n;++i)
        ans[lin[i]]=i;
    for(int i=0;i<n-1;++i)
        printf("%d ",ans[i]);
    cout<<ans[n-1]<<endl;
    return 0;
}

时间: 2024-10-07 17:54:31

【BZOJ1562】【jzyzOJ1730】【COGS409】NOI2009变换序列 二分图匹配的相关文章

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.如果有多个满足条

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的题目,果然是好题. 具

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

【题解】 [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]\)

【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

753 - A Plug for UNIX (最大流或二分图匹配)

紫书上网络流部分的第一道例题,  刚刚学了最大流,还没有理解二分图匹配 , 这里就只说一下我用最大流是怎么做的吧 . 我们可以假想一个源点,一个汇点,然后对于每一个设备的插头,从源点连一条线,对于每个插座,连一条线到汇点,且容量都为1 . 然后对于每一个转换器,从原插头到变换后的插头连一条边,因为转换器数量无穷大,所以容量为无穷大 . 这样我们就将原问题抽象成了最大流问题,巧妙的将出入路径的容量赋值为1,以此来让每一个设备匹配到唯一一个容器 .紫书上说这是二分图匹配,也许也暗含着其原理吧  .