Description

给出一个 $N$ 行 $M$ 列的矩阵A, 保证满足以下性质:

  1. $M > N$。
  2. 矩阵中每个数都是 $[0, N]$ 中的自然数。
  3. 每行中, $[1, N]$ 中每个自然数都恰好出现一次。这意味着每行中 $0$ 恰好出现 $M - N$ 次。
  4. 每列中,$[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

Sample Explanation

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

Hint

对于 20% 的数据,$M < 8, T < 8$。

对于 40% 的数据,$N < 8, T < 8$。

对于 100% 的数据,$N < 200, M < 400, T < 50$。

卖萌表情包括但不限于“\(^o^)/” (不含引号).

由于输入数据较大, 请自行优化输入方法.

时间限制:$1\texttt{s}$

空间限制:$512\texttt{MB}$

题解

稳定婚姻问题。

首先值得肯定的是每一行所选的数不能相同,那么现在就相当于 $n$ 个行匹配 $n$ 个数。

那么什么是不稳定的婚姻?如果假设数 $x$ 在第 $i$ 行选中的数之前(确保 $x$ 没有被选中的数删去),又同时选中 $x$ 的 $j$ 行中 $x$ 位置比 $i$ 行中 $x$ 位置靠前。显然这个时候是不合法的。但只要我们选第 $i$ 行的 $x$ ,再作调整就能得到合法的解。

所以归纳得出的结论就是:在一行中,偏好选在靠前面的数字。而对于每个数字,偏好其在行中的位置靠后的行。

那么就可以跑 $Gale-Shapley$ 。

 //It is made by Awson on 2018.1.18
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
using namespace std;
const int N = ;
void read(int &x) {
char ch; bool flag = ;
for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || ); ch = getchar());
for (x = ; isdigit(ch); x = (x<<)+(x<<)+ch-, ch = getchar());
x *= -*flag;
}
void write(int x) {
if (x > ) write(x/);
putchar(x%+);
} int n, m;
int alike[N+][N+], blike[N+][N+];
int achoice[N+], bchoice[N+];
queue<int>Q; void work() {
read(n), read(m);
for (int i = ; i <= n; i++)
for (int j = , tot = , x = ; j <= m; j++, x = ) {
read(x); if (x) alike[i][++tot] = x, blike[x][i] = j;
}
for (int i = ; i <= n; i++) blike[i][n+] = , bchoice[i] = n+, achoice[i] = , Q.push(i);
while (!Q.empty()) {
int a = Q.front(), b = alike[a][achoice[a]];
if (blike[b][bchoice[b]] < blike[b][a]) {
Q.pop();
if (bchoice[b] != n+) {
achoice[bchoice[b]]++;
Q.push(bchoice[b]);
}
bchoice[b] = a;
}else achoice[a]++;
}
for (int i = ; i <= n; i++) write(alike[i][achoice[i]]), putchar(' ');
}
int main() {
int t; read(t);
while (t--) {work(); if (t) putchar('\n'); }
return ;
}

[UOJ 41]【清华集训2014】矩阵变换的更多相关文章

  1. UOJ.41.[清华集训2014]矩阵变换(稳定婚姻)

    题目链接 稳定婚姻问题:有n个男生n个女生,每个男/女生对每个女/男生有一个不同的喜爱程度.给每个人选择配偶. 若不存在 x,y未匹配,且x喜欢y胜过喜欢x当前的配偶,y喜欢x也胜过y当前的配偶 的完 ...

  2. bzoj 3816&&uoj #41. [清华集训2014]矩阵变换

    稳定婚姻问题: 有n个男生,n个女生,所有女生在每个男生眼里有个排名,反之一样. 将男生和女生两两配对,保证不会出现婚姻不稳定的问题. 即A-1,B-2 而A更喜欢2,2更喜欢A. 算法流程: 每次男 ...

  3. [BZOJ3816][清华集训2014]矩阵变换(稳定婚姻问题)

    3816: 矩阵变换 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 803  Solved: 578[Submit][Status][Discuss] ...

  4. uoj #46[清华集训2014]玄学

    uoj 因为询问是关于一段连续区间内的操作的,所以对操作构建线段树,这里每个点维护若干个不交的区间,每个区间\((l,r,a,b)\)表示区间\([l,r]\)内的数要变成\(ax+b\) 每次把新操 ...

  5. uoj 41 【清华集训2014】矩阵变换 婚姻稳定问题

    [清华集训2014]矩阵变换 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/41 Description 给出 ...

  6. AC日记——【清华集训2014】奇数国 uoj 38

    #38. [清华集训2014]奇数国 思路: 题目中的number与product不想冲: 即为number与product互素: 所以,求phi(product)即可: 除一个数等同于在模的意义下乘 ...

  7. [UOJ#274][清华集训2016]温暖会指引我们前行

    [UOJ#274][清华集训2016]温暖会指引我们前行 试题描述 寒冬又一次肆虐了北国大地 无情的北风穿透了人们御寒的衣物 可怜虫们在冬夜中发出无助的哀嚎 “冻死宝宝了!” 这时 远处的天边出现了一 ...

  8. UOJ#46. 【清华集训2014】玄学

    传送门 分析 清华集训真的不是人做的啊嘤嘤嘤 我们可以考虑按操作时间把每个操作存进线段树里 如果现在点x正好使一个整块区间的右端点则更新代表这个区间的点 我们不难发现一个区间会因为不同的操作被分成若干 ...

  9. 清华集训2014 sum

    清华集训2014sum 求\[∑_{i=1}^{n}(-1)^{⌊i√r⌋}\] 多组询问,\(n\leq 10^9,t\leq 10^4, r\leq 10^4\). 吼题解啊 具体已经讲得很详细了 ...

随机推荐

  1. 贯穿程序员一生的必备开发技能——debug

    1.什么是debug debug是一种运行模式,用来跟踪程序的走向,以及跟踪程序运行过程中参数的值的变化. 2.debug的作用 debug一般用来跟踪代码的运行过程,通常在程序运行结果不符合预期或者 ...

  2. 关于hadoop集群下Datanode和Namenode无法访问的解决方案

    HDFS架构 HDFS也是按照Master和Slave的结构,分namenode,secondarynamenode,datanode这几个角色. Namenode:是maseter节点,是大领导.管 ...

  3. 每日冲刺报告--Day2

    敏捷冲刺每日报告--Day2 情况简介 今天我们三个人在一起开了会,分析了我们面临的情况以及下一阶段的计划.一个重大的改进是,我们准备把之前用txt文件格式存储订阅列表改成了文件json格式. 任务进 ...

  4. C程序第二次作业

    2-1删除字符串中数字字符 1.设计思路 (1)主要描述题目算法 第一步:遍历指针s所指的s数组. 第二步:如果 * (s+i)在0至9之间的话,则跳过此 * (s+i). 第三步:如果* (s+i) ...

  5. Linux 复习

    shift + control + +  终端窗口放大 control + -   终端窗口缩小 ls -alh > laowang.txt 重定向,并覆盖源文件内容 ls -alh >& ...

  6. New UWP Community Toolkit - RangeSelector

    概述 前面 New UWP Community Toolkit 文章中,我们对 V2.2.0 版本的重要更新做了简单回顾,其中简单介绍了 RangeSelector,本篇我们结合代码详细讲解一下 Ra ...

  7. react基础篇入门组件

    讲述一下React: 1.声明式设计-React采用声明范式,可以轻松描述应用 2.高效-React通过DOM模型,最大限度的减少dom的交互 3.灵活-React可以与已知的库或框架很好的配合 4. ...

  8. WIN10系统触摸板快捷键

    快捷的手势操作,有时候会让人脱离鼠标,只要不是非用不可的情况,基本上这些常用手势就能让我们摆脱鼠标携带不便或者桌子地方小的烦恼.iOS上的快捷手势很是受欢迎,win10上却鲜有人知晓,尤其是非开发人员 ...

  9. Vue.js和jQuery混合使用的一点注意事项

    首先,Vue 的官方是不建议直接操作 DOM 的,其优势在于视图和数据的双向绑定,而且所有DOM操作都可以用Vue实现,反而使用jQuery来操作DOM的话,会造成不必要的麻烦,DOM未渲染完成之前事 ...

  10. Dijkstra的双栈算术表达式求值算法

    这次来复习一下Dijkstra的双栈算术表达式求值算法,其实这就是一个计算器的实现,但是这里用到了不一样的算法,同时复习了栈. 主体思想就是将每次输入的字符和数字分别存储在两个栈中.每遇到一个单次结束 ...