Let us consider undirected graph G = which has N vertices and M edges. Incidence matrix of this graph is N * M matrix A = {a ij}, such that a ij is 1 if i-th vertex is one of the ends of j-th edge and 0 in the other case. Your task is to find the sum of all elements of the matrix A TA.
This problem contains multiple test cases!
The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.
The output format consists of N output blocks. There is a blank line between output blocks.
Input
The first line of the input file contains two integer numbers - N and M (2 <= N <= 10 000, 1 <= M <= 100 000). 2M integer numbers follow, forming M pairs, each pair describes one edge of the graph. All edges are different and there are no loops (i.e. edge ends are distinct).
Output
Output the only number - the sum requested.
Sample Input
1
4 4
1 2
1 3
2 3
2 4
Sample Output
18
题目链接:
题意:
给定一个有N个顶点,M条边的图,N* M的矩阵A中的元素a(i,j)为1当且仅当第i个顶点是第j条边的端点,否则为0。求AT*A的各个元素之和。AT为A的转置矩阵(M*N)。(2 <= N <= 10000 , 1 <= M <= 100000)(来自nocow)
题解:
Your task is to find the sum of all elements of the matrix A TA.
这道题要求的是所有元素的元素和!!!我竟然,竟然理解错题意了。
首先呢,我们知道,这道题表示的是一个无向图,也就是说联通1、2就相当于联通了2 、1,既然如此的话,在矩阵中不就应该是aij=aji吗,因为矩阵的逆矩阵刚好跟这个相符,那么这道题中,原矩阵跟它的逆矩阵是一样的。
a11 a12 a13 a11*(a11+a21+a31)
a21 a22 a23 ->求得的ATA等于 (此处省略好多)
a31 a32 a33
就观察最后式子的第一个元素就能发现,对于a11,如果说这一点是1的话,那么如果说括号内的元素有1的话,最后的结果就加1.
然而很不幸,a11是0,所以整体都是0
那么如果说现在是a12*(a11+a12+a13)呢?
因为a12是1,也就意味着1和2之间连通了,那么因为a12,a13为1,那么最后就应该加2.
说到这里不知道你发现了没有,我们的最后的结果加1的情况就是下面这样的:
举个例子:a12和a13之间都联通了,那么最后结果加1.
不过我们还可以进行一个转化,也就是说,既然我们知道两个连通了就加1,那么问题就可以转化为找到一个节点已经连通的个数,那么问题来了?我们该怎么找?
可以转化一个思想:就是说我们现在输入了两个节点,那么不就意味着这两个节点都多了一个边了吗?
这样找到每一个节点出现的次数以后,求它们的平方和就行了!
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=100005;
int num[maxn];
int main()
{
int T;
while(~scanf("%d",&T))
{
while(T--)
{
int num_max=0;
memset(num,0,sizeof(num));
int n,m;
cin>>n>>m;
for(int i=1; i<=m; ++i)
{
int a,b;
cin>>a>>b;
num[a]++;
num[b]++;
num_max=max(num_max,max(a,b));
}
long long num_puts=0;
for(int i=0; i<=num_max; ++i)
{
num_puts+=(long long)(num[i])*num[i];
}
printf("%lld\n",num_puts);
if(T)
printf("\n");
}
}
return 0;
}