H - Matrix Multiplication
首先我先说明一下,如果我英语不是太渣的话那么题中说的矩阵是 n∗m的矩阵。(我知道是 n∗n的邻接矩阵)。但是我看题解矩阵 A都是 n∗n的邻接矩阵
题意:
n个顶点, m个双向边,下面输入 m个边,从而生成一个矩阵 A,如果顶点 u, v之间有一条边,那么 Au v的值为1,否则为 0 。现在让你求 AT∗A 所得的矩阵的元素和。
解法:
首先因为边是双向的,所以 AT=A ,故求 A∗A的元素和即可。但很明显的是矩阵相乘肯定不行,时间复杂度太大。
我们可以转化为另一个问题,路径长度为2的所有路径个数。
可以用组合学的加法原理,因为所有路径长度为2的路径的中间节点是确定的,我们可以把问题转化为 1~ n 每个节点作为长度为2的路径的中间节点的路径条数之和,比如样例边 1 2 ,2 3,对应的所有路径有
2 1 2
1 2 1
1 2 3
3 2 1
3 2 3
2 3 2
我们可以枚举每个顶点u,顶点u作为路径长度为2的中间节点的路径个数为:顶点 u的入度 ∗顶点 u的出度, 又因为边是双边边,故每个顶点的入度等于出度。
故我们求所有顶点 u的度数平方和即可。
#include<bits/stdc++.h>
#define mset(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const ll maxn=1e4+200;
const ll inf=0x3f3f3f3f3f3f3f3f;
ll degree[maxn];
int main(){
ll ans=0;
int t,n,m,cas=0;
scanf("%d",&t);
while(t--){
if(cas)
puts("");
cas=1;
scanf("%d %d",&n,&m);
mset(degree,0);
for(int i=1;i<=m;++i){
int u,v;
scanf("%d %d",&u,&v);
degree[u]+=1;
degree[v]+=1;
}
ans=0ll;
for(int i=1;i<=n;++i){
ans+=degree[i]*degree[i];
}
cout<<ans<<endl;
}
return 0;
}