20130709 【南华大学 ACM】 新生赛第二场 【G. Matrix】

本文探讨了稀疏矩阵乘法的有效计算方法,针对仅包含0或1元素的矩阵A,通过分析矩阵A的特性,提出了利用点坐标排序来优化计算AAT的方法,以减少重复计算并提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Problem G: Matrix

Time Limit: 2 Sec  Memory Limit:128 MB

Description

To efficient calculate the multiplication of a sparse matrix is very useful in industrial filed. Let’s consider
this problem:
A is an N*N matrix which only contains 0 or 1. And we want to know the result of AAT.
Formally, we define B = AAT, Aij is equal to 1 or 0, and we know the number of 1 in matrix A is M
and your task is to calculate B.

Input

The input contains several test cases. The first line of input contains a integer C indicating the number
of the cases.
For each test case, the first line contains two integer N and M.
and each of next M lines contains two integer X and Y , which means Axyis 1.
N ≤ 100000, M ≤ 1000, C ≤ 10

Output

For each test case, it should have a integer W indicating how many element in Matrix B isn’t zero in one
line.

Sample Input

2
5 3
1 0
2 1
3 3
3 3
0 0
1 0
2 0

Sample Output

3
9

HINT

ATmeans the Transpose of matrix A, for more details, ATij= Aji.

eg:

if Matrix A is:

123

456

789

then the matrix ATis

147

258

369

----------------------------------------------------------------------------------------------------------

解题报告:


                            

以3阶矩阵为例:

                 |a11  a12  a13|  |a11  a21  a31|    
B= A*AT = |a21  a22  a23|* |a12  a22  a32| = 

                 |a31  a32  a33|  |a13  a23  a33|    

|a11*a11+a12*a12+a13*a13  a11*a21+a12*a22+a13*a23  a11*a31+a12*a32+a13*a33| 
|a21*a11+a22*a12+a23*a13  a21*a21+a22*a22+a23*a23  a21*a31+a22*a32+a23*a33| |a31*a11+a32*a12+a33*a13  a31*a21+a32*a22+a33*a23  a31*a31+a32*a32+a33*a33|


1)矩阵(方阵)行、列数,最大为 n=100000 ,如果直接申请二维数组会爆掉(10^10).

2)仔细观察题目,发现矩阵中(方阵)最多只有 m=1000 个点为“1”,其余都为“0”。

3)显然,该题的破解就需要从着手。


  1. 建立结构体存储点的横,纵坐标(x,y);
  2. 分析矩阵乘法的规律(上面以3阶矩阵为例): 
  3.  x 与 x` 决定矩阵B中第 x 行,第 x` 列的位置;
  4. 显然,与Axy项相乘的项Ax`y`,y 值必然相等( y==y` );
  5. 又由 矩阵 乘法规律,当 ( y==y` && x==x` )时,非0点有+1个;
  6. 而当只有( y==y` ),非0点重复。(+2)
  7. 【如:a11*a21存在(第1行第2列),则矩阵B第2行第1列(a21*a11也存在)值也非0。
  8. 由此,当( y==y`)时,若( x==x` )count++;否则(x!=x`)count+=2;


  1. 但由此,会引来重复计算问题:
  2. 【如:a12*a22存在(第1行第2列),则矩阵B第2行第1列(a22*a12也存在)值也非0。
  3. 【但由上可知count已经+2了,如果再执行count+=2,就会导致重复。

 

  1. 为了解决这种问题。
  2. 记录点坐标时,采用快速排序qsort(……)(包含头文件stdlib.h);
  3. 对记录点坐标的结构体数组排序(由小到大,先按x值排序,次按y值排序);
  4. 排序后进行 y值比较,判断x的情况,进行count增加。
  5. 情况如下图:
  6. 用x1,x2记录(判断x的情况,进行count增加时)的x与x` ;
  7. 得,判断条件(用来排除重复情况):( ( x>x1 || x`>x2 ) && ( x>x2 || x>x1 ) )。


代码如下(比较原始,很多没有跟上面讲到的符号匹配)。

语言乏力,请原谅……


----------------------------------------------------------------------------------------------------------

代码:

#include<stdio.h>
#include<stdlib.h>

struct p
{
	int x,y;
}p[1005],re[1005];

int qcmp(const void *a,const void *b)
{
	if( a>b )		return 1;
	else if( a<b )		return -1;
	return 0;
}

int main()
{
	int t,n,m,i,j,h,k,count,x,y;		
	scanf("%d",&t);
	while( t-- )
	{
		scanf("%d%d",&n,&m);
		for(count=h=i=0;i<m;i++)
			scanf("%d%d",&p[i].x,&p[i].y);
		qsort(p,m,sizeof(p[0]),qcmp);
		for(x=y=-1,i=0;i<m;i++)
			for(j=i;j<m;j++)
				if( ( p[i].y == p[j].y )
				 && ( p[i].x>x || p[j].x>y ) 
				 && ( p[i].x>y || p[j].x>x ) )
				{
					x=p[i].x;
				 	y=p[j].x;
					if( x == y )
						count++;
					else
						count+=2;
				}
		printf("%d\n",count);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值