zoukankan      html  css  js  c++  java
  • 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,其中
    定义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
    【数据规模和约定】
    20%的数据中N≤50;
    60%的数据中N≤500;
    100%的数据中N≤10000。
     
    题解:
    二分图匹配+匈牙利算法
    设原序列值为x[0],x[1],x[2]......x[n-1],要变成的序列值为y[0],y[1],y[2]......y[n-1].
    原序列也就是0,1,2......n-1,即x[0]=0,x[1]=1,x[2]=2......x[n-1]=n-1.
    首先,通过样例可以想到每一个值x[i]可以变成的 y[i]的取值最多只有两个,但为什么,证明如下:
     
    设a=| x[i] - y[i] |,且a ≤ (n-a),其中a,(n-a)都为差值(由题目中可知)
     
    对于每一个x[i],我们有y[i]=x[i]±a或y[i]=x[i]±(n-a).
     
    因为每个x[i]和y[i]要满足0≤x[i]≤n-1,0≤y[i]≤n-1,且y[i]=x[i]±a或y[i]=x[i]±(n-a).
     
    则可以得到:  x[i]+a≤n-1   --------------   (1)式
                       x[i]-a≥0       --------------   (2)式
                       x[i]+(n-a)≤n-1  ----------    (3)式
                       x[i]-(n-a)≥0   -------------   (4)式
     
    (3)式化简可得 : x[i]-a≤-1
     
    (4)式移项可得 : x[i]+a≥n
     
    观察四个式子,我们可以发现 :(1)式 和 (4)式 是矛盾的,(2)式 和(3)式 是矛盾的.
     
    所以,我们只能在 (1)式 和 (4)式 中选一个,(2)式 和(3)式 中选一个.
     
    证毕.
     
    然后,有了这个结论,我们就把题目变成了 :给出0...n-1,还给出了每个数的变化量(变化量给的是绝对值,也就是可以变化的差值),每个数都必须要 变化 且 恰好变化给定的差值 ,每个数可以变成两个数(上面已经证明),让你 变成0...n-1 且 使变后的序列 字典序 最小。
    就可以跑匈牙利了(迷之时间复杂度。。。)
    其实就是要判断是否 完美匹配 。若没有 完美匹配 ,则输出无解。
    注意匈牙利要倒着跑,可以跑出 字典序 最小。
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define MAXN 10010
     4 int BF[MAXN],BF1[MAXN],d[MAXN],prey[MAXN],n,f[MAXN][2];
     5 //bool f[MAXN][MAXN];
     6 bitset<MAXN> vis;
     7 int read()
     8 {
     9     int s=0,fh=1;char ch=getchar();
    10     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
    11     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
    12     return s*fh;
    13 }
    14 int Xyl(int u)
    15 {
    16     int i,v;
    17     for(i=0;i<=1;i++)
    18     {
    19         v=f[u][i];
    20         if(vis[v]==0)
    21         {
    22             vis[v]=1;
    23             if(Xyl(BF[v])==1||BF[v]==0)
    24             {
    25                 BF[v]=u;
    26                 BF1[u]=v;
    27                 return 1;
    28             }
    29         }
    30     }
    31     return 0;
    32 }
    33 int main()
    34 {
    35     freopen("transform.in","r",stdin);
    36     freopen("transform.out","w",stdout);
    37     int i,ans,dd,gs;
    38     n=read();
    39     memset(f,false,sizeof(f));
    40     for(i=0;i<n;i++)
    41     {
    42         d[i]=read();dd=n-d[i];
    43         gs=-1;
    44         if(i-d[i]>=0)f[i][++gs]=i-d[i];
    45         if(i+d[i]<=n-1)f[i][++gs]=i+d[i];
    46         if(i-dd>=0)f[i][++gs]=i-dd;
    47         if(i+dd<=n-1)f[i][++gs]=i+dd;
    48         if(f[i][0]>=f[i][1])swap(f[i][0],f[i][1]);
    49     }
    50     memset(BF,0,sizeof(BF));ans=0;
    51     memset(prey,-1,sizeof(prey));
    52     for(i=n-1;i>=0;i--)
    53     {
    54         vis.reset();
    55         ans+=Xyl(i);
    56         //prey[i]=BF1[i];
    57     }
    58     if(ans!=n)printf("No Answer");
    59     else
    60     {
    61         //for(i=0;i<n;i++)BF1[BF[i]]=i;
    62         for(i=0;i<n;i++)printf("%d ",BF1[i]);
    63     }
    64     fclose(stdin);
    65     fclose(stdout);
    66     return 0;
    67 }
  • 相关阅读:
    Python中引用自定义类的方法
    使用js判断a是不是NaN 类型
    实现小数保留并四舍五入
    C# 生成全球唯一标识符GUID
    VS2008 激活
    Android 获取当前IP地址
    Android 双屏异显的实现
    用友系统的本币和原币
    .net core Json字符串的序列化和反序列化通用类源码,Newtonsoft和DataContractJsonSerializer性能对比
    建议收藏备用:.net core使用QRCoder生成普通二维码和带Logo的二维码详细使用教程,源码已更新至开源模板
  • 原文地址:https://www.cnblogs.com/Var123/p/5399165.html
Copyright © 2011-2022 走看看