[caioj 1486及hdu 2157,利用矩陣乘法解決的經典題目八]多少條路呢??

給定一個有向圖,有n個點,m條邊。求A點到B點恰好經過k條邊的方案數(可走重複邊)。

這道題表面上是dp,dfs什麼的,但實際上是一道矩陣乘法加快速冪的裸題。爲什麼呢,其實是因爲矩陣乘法它那相乘的特殊。首先把有向圖轉換成鄰接矩陣X(可達矩陣),即如果x點能到達y點,那麼a[x][y]=1,如果x,y兩點之間不能到達,那麼a[x][y]=0。假設A矩陣爲X的平方,那麼A[i][j]=ΣX[i][k]*X[k][j],這其實就是乘法原理與加法原理的結合,那麼這個A矩陣的A[i][j]就表示着i到j經過了2條邊的方案數,懂了嗎。那麼經過k條邊,只需用快速冪將X平方k次就可以了,這題就解決了。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
struct node
{
    int a[25][25];
    node()
    {
        memset(a,0,sizeof(a));
    }
};
int n;
node chengfa(node a,node b)
{
    node c;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            for(int k=1;k<=n;k++)
            {
                c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%1000;
            }
        }
    }
    return c;
}
int main()
{
    int m,t;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0 && m==0)break;
        node pre,ans;
        for(int i=1;i<=m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            pre.a[x+1][y+1]=1;
        }
        for(int i=1;i<=n;i++)ans.a[i][i]=1;
        scanf("%d",&t);
        while(t--)
        {
            int x,y,k;
            scanf("%d%d%d",&x,&y,&k);
            x++;y++;
            node s=ans,ss=pre;
            while(k>0)
            {
                if(k%2==1)s=chengfa(ss,s);
                ss=chengfa(ss,ss);
                k/=2;
            }
            printf("%d\n",s.a[x][y]%1000);
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章