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
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
两组输入数据是相同的。由于结果不唯一,你可以给出任意一组合法答案
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 }