BZOJ1562jzyzOJ1730COGS409NOI2009变换序列 二分图匹配

Posted Strork

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1562jzyzOJ1730COGS409NOI2009变换序列 二分图匹配相关的知识,希望对你有一定的参考价值。

 

【问题描述】

       对于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;
}
View Code

 

以上是关于BZOJ1562jzyzOJ1730COGS409NOI2009变换序列 二分图匹配的主要内容,如果未能解决你的问题,请参考以下文章

jzyzOJ 1658bzoj1798改编

bzoj3196: Tyvj 1730 二逼平衡树 树套树

bzoj1730[Usaco2005 dec]Barn Expansion 牛棚扩张

bzoj 3196: Tyvj 1730 二逼平衡树

bzoj3196: Tyvj 1730 二逼平衡树

bzoj3196: Tyvj 1730 二逼平衡树