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 }

 

posted @ 2017-09-12 17:20  wfj_2048  阅读(276)  评论(0编辑  收藏  举报