Zoj 2316 Matrix Multiplication(思路)

H - Matrix Multiplication

ZOJ - 2316

首先我先说明一下,如果我英语不是太渣的话那么题中说的矩阵是nmn*m的矩阵。(我知道是nnn*n的邻接矩阵)。但是我看题解矩阵AA都是nnn*n的邻接矩阵

题意:

nn​个顶点,mm​个双向边,下面输入mm​个边,从而生成一个矩阵AA​,如果顶点uu​,vv​之间有一条边,那么Au vA_{u~v}​的值为1,否则为00​ 。现在让你求ATAA^{T}*A​ 所得的矩阵的元素和。

解法:

​ 首先因为边是双向的,所以AT=AA^{T}=A ,故求AAA*A的元素和即可。但很明显的是矩阵相乘肯定不行,时间复杂度太大。

​ 我们可以转化为另一个问题,路径长度为2的所有路径个数。

​ 可以用组合学的加法原理,因为所有路径长度为2的路径的中间节点是确定的,我们可以把问题转化为11~nn 每个节点作为长度为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的中间节点的路径个数为:顶点uu的入度*顶点uu的出度, 又因为边是双边边,故每个顶点的入度等于出度。

​ 故我们求所有顶点uu的度数平方和即可。

#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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章