• bzoj3816 矩阵变换


    Description

    给出一个 N 行 M 列的矩阵A, 保证满足以下性质:
    M>N。
    矩阵中每个数都是 [0,N] 中的自然数。
    每行中, [1,N] 中每个自然数都恰好出现一次。这意味着每行中 0 恰好出现 M−N 次。
    每列中,[1,N] 中每个自然数至多出现一次。
    现在我们要在每行中选取一个非零数,并把这个数之后的数赋值为这个数。我们希望保持上面的性质4,即每列中,[1,N] 中每个自然数仍然至多出现一次。

    Input

    第一行一个正整数 T,表示数据组数。
    后面包含 T 组数据,各组数据之间无空行。每组数据以两个正整数 N,M 开始,接下来 N 行,每行 M 个用空格隔开的整数,意义如题所述。

    Output

    对于每组数据输出一行。如果有解,则输出 N 个整数,依次表示每一行取的数是多少。(这应该是一个 1 到 N 的排列)如果无解,则输出任意卖萌表情。

    Sample Input

    2
    5 10
    0 1 0 2 3 0 0 4 0 5
    2 0 3 0 0 1 0 5 4 0
    4 2 1 0 0 0 3 0 5 0
    0 3 0 4 0 5 0 1 2 0
    1 0 0 3 2 4 5 0 0 0
    5 10
    0 1 0 2 3 0 0 4 0 5
    2 0 3 0 0 1 0 5 4 0
    4 2 1 0 0 0 3 0 5 0
    0 3 0 4 0 5 0 1 2 0
    1 0 0 3 2 4 5 0 0 0

    Sample Output

    4 5 3 1 2
    5 4 3 1 2

    explanation
    两组输入数据是相同的。由于结果不唯一,你可以给出任意一组合法答案

    HINT

    对于 100% 的数据,N<200,M<400,T<50。
    卖萌表情包括但不限于“(^o^)/” (不含引号).
    由于输入数据较大, 请自行优化输入方法.
    请不要提交,期待SPJ

    正解:稳定婚姻问题。

    我们可以发现,每一行更趋于选这一行靠前的数,每个数更趋于选它靠后的那一行。

    进一步发现,如果每一行选的数没有$x$好,同时$x$选的行也没有这一行好,那么就会出现不合法情况。

    所以这就是一个稳定婚姻问题,把行当成男生,数当成女生,跑一遍就行了。

     1 #include <bits/stdc++.h>
     2 #define il inline
     3 #define RG register
     4 #define ll long long
     5 
     6 using namespace std;
     7 
     8 int bg[210][210],gb[210][210],c[210],p[210],q[210],Q[1100010],n,m;
     9 
    10 il int gi(){
    11   RG int x=0,q=1; RG char ch=getchar();
    12   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    13   if (ch=='-') q=-1,ch=getchar();
    14   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    15   return q*x;
    16 }
    17 
    18 il void work(){
    19   n=gi(),m=gi();
    20   for (RG int i=1;i<=n;++i)
    21     for (RG int j=1;j<=n;++j) bg[i][j]=gb[i][j]=0;
    22   for (RG int i=1;i<=n;++i) c[i]=0;
    23   for (RG int i=1;i<=n;++i)
    24     for (RG int j=1,k;j<=m;++j){
    25       k=gi(); if (!k) continue;
    26       bg[i][++c[i]]=k,gb[k][i]=j;
    27     }
    28   RG int h=0,t=0;
    29   for (RG int i=1;i<=n;++i) Q[++t]=i,c[i]=p[i]=q[i]=0;
    30   while (h<t){
    31     RG int x=Q[++h],v=bg[x][++c[x]];
    32     if (!q[v]) q[v]=x,p[x]=v;
    33     else if (gb[v][x]>gb[v][q[v]]) Q[++t]=q[v],q[v]=x,p[x]=v;
    34     else --h;
    35   }
    36   for (RG int i=1;i<=n;++i) printf("%d ",p[i]); puts(""); return;
    37 }
    38 
    39 int main(){
    40 #ifndef ONLINE_JUDGE
    41   freopen("matrix.in","r",stdin);
    42   freopen("matrix.out","w",stdout);
    43 #endif
    44   RG int T=gi();
    45   while (T--) work();
    46   return 0;
    47 }
  • 相关阅读:
    <Error>: CGContextRestoreGState
    Google 常用镜像收集
    NSCharacterSet 详解
    JAVA并发,CyclicBarrier
    JAVA并发,CountDownLatch使用
    JAVA并发,经典死锁案例-哲学家就餐
    Git-常用命令集合
    (转)《JAVA与模式》之模板方法模式
    JAVA并发,同步锁性能测试
    《转》JAVA并发编程:volatile关键字解析
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7508965.html
Copyright © 2020-2023  润新知