【hrbust2294】方方正正

题意

哈理工2016级新生程序设计全国邀请赛C题
一个r行c列的01矩阵,告诉你每行的和、每列的和,问是否存在这样的矩阵?

题解

首先,行和和列和之和要相等,否则一定是NO。
然后根据Gale-Ryser定理判断存在性:

求出(R^*=(r_1^*,r_2^*,...,r_m^*),r_i^*=行和大于等于i的行数)
只要(R^*preceq S)就存在,这里的S就是列和向量。
二元操作符(preceq)的定义是:向量x的前i大的数之和总是比向量y的前i大的数之和要小或者相等,那么(xpreceq y)

代码

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 100006
int i,m,n;
long long rs,cs,r[N],c[N],w[N];
int main(){
    while(~scanf("%d%d",&m,&n)){//m行n列
        rs=cs=0;
        memset(w,0,sizeof w);

        for(i=1;i<=m;i++){
            scanf("%d",&r[i]);
            rs+=r[i];
            w[r[i]]++;//w[i]:行和为i的有几个
        }

        for(i=1;i<=n;i++){
            scanf("%d",&c[i]);
            cs+=c[i];
        }

        if(rs!=cs){
            puts("NO");
            continue;
        }

        sort(c+1,c+1+n,greater<long long>());

        for(i=n;i;i--)w[i]+=w[i+1];//w[i]:行和大于等于i的有几个

        for(i=1;i<=n;i++){
            c[i]+=c[i-1];
            w[i]+=w[i-1];
            if(c[i]>w[i])//w就是R*,若c[i]>w[i]表明R*不能盖过S
                break;
        }

        if(i==n+1) puts("YES");
        else puts("NO");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/flipped/p/6213178.html