Kick Start 2021 Round A:
Checksum
Grace and Edsger are constructing a N×N boolean matrix A. The element in i-th row and j-th column is represented by Ai,j. They decide to note down the checksum (defined as bitwise XOR of given list of elements) along each row and column. Checksum of i-th row is represented as Ri. Checksum of j-th column is represented as Cj.
For example, if N=2, A=[1101], then R=[10] and C=[01].
Once they finished the matrix, Edsger stores the matrix in his computer. However, due to a virus, some of the elements in matrix A are replaced with −1 in Edsger’s computer. Luckily, Edsger still remembers the checksum values. He would like to restore the matrix, and reaches out to Grace for help. After some investigation, it will take Bi,j hours for Grace to recover the original value of Ai,j from the disk. Given the final matrix A, cost matrix B, and checksums along each row ® and column ©, can you help Grace decide on the minimum total number of hours needed in order to restore the original matrix A?
题目大意
Grace在尝试复原一个N × \times ×N的01矩阵(1 ≤ \leq ≤ N ≤ \leq ≤ 500),第i行,第j列的值为Ai,j(若Ai,j=-1的,表示值未知)。他已知每一行与每一列的异或和Ri,Ci,同时他也可以花费Bi,j小时(1 ≤ \leq ≤ Bi,j ≤ \leq ≤ 1000)去向Grace询问Ai,j的值。他最少需要多少时间才能复原矩阵?
思路分析
注意到,对于任何一行或一列,如果我们只有一个值是未知的,我们可以用所有其他值异或上异或和便可以求解这个值;如果有至少两个位置未知,那么我们便无法求解。考虑每一个Ai,j=-1的位置,我们每一行和每一列最多有1个值是可以通过当列(行)的异或值自己求出来的,那么我们应该尽量选取Bi,j更大的值来节省时间。怎样找到这样的点的集合呢?由于每列(行)最多使用一次,我们可以把每一行(列)看成一个点,可以把每个Ai,j看成是把第i行和第j列连接起来的边,在生成图中找最大生成树,组成最大生成树的边集就是我们要找的点集。答案为所有Ai,j=-1的Bi,j之和减去最大生成树的边权和。一共最多n2个点,那么这个算法时间复杂度是O(n2log(n2)),也就是O(n2log(n))的。
重要代码示例
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(a[i][j]==-1)
{
ans+=b[i][j];
vec[b[i][j]].push_back({i,j+n});//连接第i行,第j列,边权为b[i][j]
}
}
}
//最大生成树
for(int val=1000;val;val--)//权值从大到小
{
for(auto p:vec[val])
{
int x=ff(p.first),y=ff(p.second);
if(x!=y)
{
ans-=val;//找到了生成树里的边
fa[x]=y;
}
}
}
本题难度比前三题要高出一些,转成图论问题的思路更多是靠经验了,不过整体难度并不高。那么本轮比赛题解至此完结!由于是开年第二轮,总体还是非常友好的,很适合新手提高信心参加!