zoukankan      html  css  js  c++  java
  • UOJ #41. 【清华集训2014】矩阵变换

    #41. 【清华集训2014】矩阵变换

    链接

    分析:

      神题!

      这题可以转化为稳定婚姻问题。每行喜欢出现尽量靠左的数,每个数喜欢它出现位置(这个数在这行中出现的位置)尽量靠右的行。要求每一行匹配一个数,每一个数匹配一行。

      稳定婚姻问题中不合法的匹配是指:对于每一个人,在他心目中比他当前的伴侣更好的异性,都不会认为他也是一个更好的选择。(摘自Matrix67)。

      可以发现,此题的不合法匹配(一列中出现两个相同的数)与稳定婚姻问题的不合法匹配相似。

      即在一行中选择一个数是合法匹配,那么这个数在当前位置的右边没有这个数的行(更优的行,保证满足条件),如果一个数选择了一个行,那么其他行的这个数的位置的右边是没有这个数。  

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 
     5 inline int read() {
     6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
     7     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
     8 }
     9 
    10 const int N = 510;
    11 int order[N][N],pref[N][N],cur[N],cnt[N],Boys[N],Girls[N];
    12 int a[N][N],q[50010],L,R; // q的数据范围!!! 
    13 
    14 void Link(int u,int v) {
    15     int t = Girls[v];
    16     if (t) {
    17         Boys[t] = 0;
    18         q[++R] = t;
    19     }
    20     Boys[u] = v;
    21     Girls[v] = u;
    22 }
    23 void solve() {
    24     int n = read(),m = read();
    25     L = 1,R =  0;
    26     memset(Boys,0,sizeof(Boys));
    27     memset(Girls,0,sizeof(Girls));
    28     memset(cnt,0,sizeof(cnt));
    29     for (int i=1; i<=n; ++i) {
    30         cur[i] = 1;
    31         q[++R] = i;
    32         int p = 0;
    33         for (int j=1; j<=m; ++j) {    
    34             a[i][j] = read();
    35             if (a[i][j]) pref[i][++p] = j;
    36         }
    37     }
    38     for (int j=m; j>=1; --j) {
    39         for (int i=1; i<=n; ++i) {
    40             if (a[i][j]) order[a[i][j]][i] = ++cnt[a[i][j]];
    41         }
    42     }
    43     while (L <= R) {
    44         int u = q[L++];
    45         int v = a[u][pref[u][cur[u]++]];
    46         if (!Girls[v]) Link(u,v);
    47         else if (order[v][u] < order[v][Girls[v]]) Link(u,v);
    48         else q[++R] = u;
    49     }
    50     for (int i=1; i<=n; ++i) 
    51         printf("%d ",Boys[i]);
    52     puts("");
    53 }
    54 int main() {
    55     int Case = read();
    56     while (Case--) solve();    
    57     return 0;
    58 }
  • 相关阅读:
    Linux应急响应(三):挖矿病毒
    Linux应急响应(二):捕捉短连接
    Linux应急响应(一):SSH暴力破解
    Window应急响应(四):挖矿病毒
    Window应急响应(三):勒索病毒
    Window应急响应(二):蠕虫病毒
    openresty开发系列10--openresty的简单介绍及安装
    openresty开发系列4--nginx的配置文件说明
    openresty开发系列3--nginx的平滑升级
    openresty开发系列2--nginx的简单安装,正向、反向代理及常用命令和信号控制介绍
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9276852.html
Copyright © 2011-2022 走看看