zoukankan      html  css  js  c++  java
  • BZOJ 1562 [NOI2009] 变换序列

    [NOI2009] 变换序列

    [题解]

    就是有一个序列,每个位置可以填两个数,不可重复,问最小字典序。

    显然,可以建一个二分图,判合法就是找完美匹配。

    那怎么弄最小字典序呢?有好多种解法,我这里给出了两种。

    解法一:

    先求出它的一个完美匹配,把每个点扫一遍,如果它连的点是它能连的最小的了,就不管他,否则强制将当前节点与其能连的最小点对应,这时从这个点找增广路,如果有,就算修正成功,否则修正失败。

    这个方法的好处是通用,时间复杂度O(n*n)

    解法二:

    从最后一个点开始求增广路,求增广路时优先考虑序号较小点。

    证明:daolao博客

    代码:

    这里给出解法二的代码。

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #include<string>
    #include<cmath>
    #include<queue>
    #define SIZE 100005
    #define rint register int
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x*f;
    }
    inline void write(int x)
    {
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10+'0');
        return ;
    }
    
    int n,match[SIZE],ans[SIZE],cnt;
    int d[SIZE],vis[SIZE],f[3][SIZE];
    
    int dfs(int x)
    {
        for(rint i=1;i<=2;++i)
        {
            int y=f[i][x];if(vis[y]) continue;
            vis[y]=1;
            if(match[y]==-1 || dfs(match[y]))
            {
                match[y]=x;ans[x]=y;
                return 1;
            }
        }
        return 0;
    }
    
    inline void clear()
    {
        memset(match,-1,sizeof(match));
        memset(ans,0,sizeof(ans));
    }
    
    int main()
    {
        n=read();clear();
        for(rint i=0;i<n;++i) d[i]=read();
        for(rint i=0;i<n;++i)
        {
            int a=(i-d[i]+n)%n,b=(i+d[i])%n;
            if(a>b) swap(a,b);
            f[1][i]=a,f[2][i]=b;
        }
        for(rint i=n-1;i>=0;--i)
        {
            memset(vis,0,sizeof(vis));
            if(dfs(i)) ++cnt;
        }
        if(cnt<n) return puts("No Answer"),0;
        for(rint i=0;i<n;++i)
        {
            write(ans[i]);
            if(i!=n) cout<<" ";
        } 
        return 0;
    }
    View Code
  • 相关阅读:
    洛谷 P3391 文艺平衡树
    [ZJOI2008]杀蚂蚁 Solution
    POJ P3667 Hotel——solution
    洛谷 P2469 [SDOI2010]星际竞速 解题报告
    POJ P2318 TOYS与POJ P1269 Intersecting Lines——计算几何入门题两道
    【linux】基础知识学习
    【linux】打包压缩命令
    【python】类file文件处理
    【python】使用asyncore进行异步通信
    【python】命令行解析工具getopt用法
  • 原文地址:https://www.cnblogs.com/mxrmxr/p/10350636.html
Copyright © 2011-2022 走看看