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

【清华集训2014】矩阵变换

Time Limit: 20 Sec  Memory Limit: 256 MB

题目连接

http://uoj.ac/problem/41

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

HINT

题意

题解:

行是男孩, 数是女孩.
一行喜欢在这行靠前的数.
数喜欢她出现的靠后的行.
然后跑婚姻稳定问题就好啦~

代码:

//qscqesze
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 200001
#define mod 10007
#define eps 1e-9
int Num;
char CH[20];
//const int inf=0x7fffffff;   //нчоч╢С
const int inf=0x3f3f3f3f;
/*

inline void P(int x)
{
    Num=0;if(!x){putchar(‘0‘);puts("");return;}
    while(x>0)CH[++Num]=x%10,x/=10;
    while(Num)putchar(CH[Num--]+48);
    puts("");
}
*/
inline ll read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
inline void P(int x)
{
    Num=0;if(!x){putchar(‘0‘);puts("");return;}
    while(x>0)CH[++Num]=x%10,x/=10;
    while(Num)putchar(CH[Num--]+48);
    puts("");
}
//**************************************************************************************

int a[500][500];
int pa[500][500];
int pc[500];
int qc[500];
int main()
{
    int t=read();
    while(t--)
    {
        memset(a,0,sizeof(a));
        memset(pa,0,sizeof(pa));
        memset(pc,0,sizeof(pc));
        memset(qc,0,sizeof(qc));
        int n=read(),m=read();
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                a[i][j]=read();
                if(a[i][j])
                    pa[i][a[i][j]]=j;
            }
        }
        for(int i=1;i<=n;i++)
        {
            int p=i;
            while(1)
            {
                while(!a[p][pc[p]])
                    pc[p]++;
                int v=a[p][pc[p]];
                if(!qc[v])
                {
                    qc[v]=p;
                    break;
                }
                int q=qc[v];
                if(pa[p][v]>pa[q][v])
                    pc[q]++,qc[v]=p,p=q;
                else
                    pc[p]++;
            }
        }
        for(int i=1;i<=n;i++)
            printf("%d ",a[i][pc[i]]);
        printf("\n");
    }
}
时间: 2024-08-25 00:37:52

uoj 41 【清华集训2014】矩阵变换 婚姻稳定问题的相关文章

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

题目链接 稳定婚姻问题:有n个男生n个女生,每个男/女生对每个女/男生有一个不同的喜爱程度.给每个人选择配偶. 若不存在 x,y未匹配,且x喜欢y胜过喜欢x当前的配偶,y喜欢x也胜过y当前的配偶 的完备匹配,则称这是一个稳定匹配. 稳定匹配一定存在,且存在一个\(O(n^2)\)的算法: 任选一个未匹配的男生x,按x的喜爱程度从大到小枚举每个女生,若当前女生没有配偶或喜欢x胜过喜欢当前配偶,则与x匹配.直到所有男生都匹配. 这一题我们用行表示男生,n个数表示女生.喜爱程度为:行更喜欢靠前的数,数

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

稳定婚姻问题: 有n个男生,n个女生,所有女生在每个男生眼里有个排名,反之一样. 将男生和女生两两配对,保证不会出现婚姻不稳定的问题. 即A-1,B-2 而A更喜欢2,2更喜欢A. 算法流程: 每次男生向自己未追求过的排名最高女生求婚. 然后每个有追求者的女生在自己现男友和追求者中选择一个最喜欢的接受,然后拒绝其他人. 算法一定可以结束. 因为如果最后有一个男生单身,那他一定把所有女生都追求过一遍,说明没有女生单身,产生矛盾. #include<iostream> #include<cs

线性基 uoj 36 清华集训2014 玛里苟斯

http://uoj.ac/problem/36 感觉挺可做的但是不会.. \(k=1\)按位扫就好了 出现\(1\)概率就是\(0.5\) \(k=2\)要特殊处理 设xor后的数是\(b_1 b_2 \dots b_n\) 计算平方贡献就好了\(\sum_{i,j}b_i b_j 2^{i+j}*p\) \(p\)存在一位\(i\),\(j\)不同的话是1/4 否则就是1/2 \(k\geq3\) 首先要知道随机选数的话 如果维护的集合可以通过xor算子得到\(x\) 那么\(x\)与答案无

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

uoj 因为询问是关于一段连续区间内的操作的,所以对操作构建线段树,这里每个点维护若干个不交的区间,每个区间\((l,r,a,b)\)表示区间\([l,r]\)内的数要变成\(ax+b\) 每次把新操作加入线段树中下一个叶子,然后如果某个节点里所有操作都加进去了,就条到父亲,把两个儿子的信息合并到父亲上.这里合并就是把两个区间集合合并成一个,例如两个区间\([a,c]\)和\([b,d](a\le b\le c\le d)\)会合并成\([a,b),[b,c),[c,d]\).合并出来的区间如果

「清华集训2014」矩阵变换

「清华集训2014」矩阵变换 解题思路 问题转化为找一个行与选的数字的完美匹配,记 \(pos[i][j]\) 为数字 \(i\) 在第 \(j\) 行的出现位置,要求不存在匹配边 \((a,b),(c,d)\) 使得 \(pos[b][a] < pos[b][c]\ \& \ pos[d][c] > pos[b][c]\) . 观察发现,这个式子相当于让一条边的权值看做 \(pos[x][y]\) ,当存在一个行与一个数没有匹配但是强行让它们匹配后数的权值会变大,行的权值会变小,这个

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

#38. [清华集训2014]奇数国 思路: 题目中的number与product不想冲: 即为number与product互素: 所以,求phi(product)即可: 除一个数等同于在模的意义下乘以一个数的逆元: 代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 100005

清华集训2014 做题记录

清华集训2014做题记录 已完成 [清华集训2014]玛里苟斯 [清华集训2014]主旋律 [清华集训2014]奇数国 [清华集训2014]矩阵变换 [清华集训2014]sum [清华集训2014]虫逢 [清华集训2014]玄学 [清华集训2014]文学 未完成 [清华集训2014]卡常数 [清华集训2014]简单回路 [清华集训2014]Router [清华集训2014] Breaking Bomber 写一题要膜一题题解,膜完题解膜代码,膜完代码膜指导,膜了好几天了还有四个题没做. [清华集

「清华集训2014」主旋律

「清华集训2014」主旋律 这个题好难难啊,我想了一个小时连50分都不会,只能去摸周指导了. 我们试图直接爆算集合 \(S\) 的非强连通导出子图数量,考虑将这个导出子图的所有强连通分量缩点后,一定是一个点数 \(\geq 2\) 的 \(\text{DAG}\) .即缩完以后至少要有一个入度为 \(0\) 的点,这个条件充分性显然,必要性考虑如果不存在入度为 \(0\) 的点,那么一定存在一个环,说明并没有将所有强连通分量缩掉.然后我们枚举入度为 \(0\) 的点集 \(T\) ,记 \(F(

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

传送门 分析 清华集训真的不是人做的啊嘤嘤嘤 我们可以考虑按操作时间把每个操作存进线段树里 如果现在点x正好使一个整块区间的右端点则更新代表这个区间的点 我们不难发现一个区间会因为不同的操作被分成若干块,每块对应序列上不同的区间 于是查询时对于每个线段树上区间查询时二分查找当前点在哪一块中即可 代码 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include&