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

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