zoukankan      html  css  js  c++  java
  • 【BZOJ3816】【清华集训2014】矩阵变换 稳定婚姻问题

    题目描述

      给出一个(n)(m)列的矩阵(A), 保证满足以下性质:

       1.(m>n)

       2.矩阵中每个数都是([0,n])中的自然数。

       3.每行中,([1,n])中每个自然数都恰好出现一次。这意味着每行中(0)恰好出现(m−n)次。

       4. 每列中,([1,n])中每个自然数至多出现一次。

    现在我们要在每行中选取一个非零数,并把这个数之后的数赋值为这个数。我们希望保持上面的性质4,即每列中,([1,n])中每个自然数仍然至多出现一次。

      (nleq 200,mleq 400)

    题解

      建立稳定婚姻问题的模型。

      把行看成男士,把数看成女士。每行喜欢出现靠左的数,每个数喜欢出现位置(这个数在这行中出现的位置)靠右的行。

      为什么这样一定合法?

      假设有这样的情况:

    [x:uuuuuuuuuuu\ y:~~~~~u~~~~~~~~vvvvv ]

      那么在第(y)行中,(y)会更喜欢(u)(因为比(v)出现位置靠左)。(u)也会更喜欢(y)(因为出现位置靠右),那么就不是一个合法解。

      其实比读入还快。

      时间复杂度:(O(nm))

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    #include<queue>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    void rd(int &s)
    {
    	int c;
    	while((c=getchar())<'0'||c>'9');
    	s=c-'0';
    	while((c=getchar())>='0'&&c<='9')
    		s=s*10+c-'0';
    }
    int a[210][410];
    int n,m;
    int b[210][210];
    int now[210];
    int c[210][210];
    int d[210];
    queue<int> q;
    void solve()
    {
    //	scanf("%d%d",&n,&m);
    	rd(n);
    	rd(m);
    	int i,j;
    	memset(now,0,sizeof now);
    	for(i=1;i<=n;i++)
    		for(j=1;j<=m;j++)
    		{
    //			scanf("%d",&a[i][j]);
    			rd(a[i][j]);
    			if(a[i][j])
    			{
    				b[i][++now[i]]=a[i][j];
    				c[a[i][j]][i]=j;
    			}
    		}
    	for(i=1;i<=n;i++)
    	{
    		q.push(i);
    		now[i]=1;
    	}
    	memset(d,0,sizeof d);
    	while(!q.empty())
    	{
    		int x=q.front();
    		q.pop();
    		int v=b[x][now[x]];
    		if(d[v]&&c[v][x]<c[v][d[v]])
    		{
    			now[x]++;
    			q.push(x);
    		}
    		else
    		{
    			if(d[v])
    				q.push(d[v]);
    			d[v]=x;
    		}
    	}
    	for(i=1;i<=n;i++)
    		printf("%d ",b[i][now[i]]);
    	printf("
    ");
    }
    int main()
    {
    	freopen("d2t3.in","r",stdin);
    	freopen("d2t3.out","w",stdout);
    	int t;
    //	scanf("%d",&t);
    	rd(t);
    	while(t--)
    		solve();
    	return 0;
    }
    
  • 相关阅读:
    oracle_使用udev绑定磁盘方法
    Android studio实现简单的CRUD
    Android Studio无法打印Logout日志
    迭代法求平方根
    实现Hibernate框架的CRUD
    Android Studio连接真机调试
    Java项目学习笔记(一)
    绝对路径${pageContext.request.contextPath}
    request、response的setCharacterEncoding与response的setContentType
    java中的@Override标签
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8513151.html
Copyright © 2011-2022 走看看