首页 > 代码库 > HDU 2254 奥运(矩阵)

HDU 2254 奥运(矩阵)

题目地址:HDU 2254

必须得吐槽一下。。这题的数据是又弱又坑。。样例不过都能AC。。还有。。居然还有重边。。WA了一晚上。。

吐槽完毕,言归正传。。

根据离散数学里面的可达矩阵的性质,我们知道一个有向图的邻接矩阵的前n次幂的和即为可达矩阵,那么要求[t1-t2]之内的路径的条数,因为题目说了t1 = 0的时候为0。那么假设邻接矩阵为A,那么要求的就是A^(t1-1)+A^(t1)+...+A^(t2-1),为什么是从t1-1开始呢,因为邻接矩阵本身代表走一步的结果。

然后再加上离散化就可以做了。

代码如下:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>

using namespace std;
#define LL __int64
const int mod=2008;
int n;
LL q[40];
struct matrix
{
    int ma[32][32];
} mat[10002];
matrix Mult(matrix x, matrix y)
{
    int i, j, k;
    matrix tmp;
    memset(tmp.ma,0,sizeof(tmp.ma));
    for(i=0; i<n; i++)
    {
        for(k=0; k<n; k++)
        {
            for(j=0; j<n; j++)
            {
                tmp.ma[i][j]=(tmp.ma[i][j]+x.ma[i][k]*y.ma[k][j])%mod;
            }
        }
    }
    return tmp;
}
int find1(LL x)
{
    int i;
    for(i=0; i<n; i++)
    {
        if(q[i]==x)
        {
            return i;
        }
    }
    return -1;
}
void Pow()
{
    for(int i=1; i<=10001; i++)
    {
        mat[i]=Mult(mat[i-1],mat[0]);
    }
}
int main()
{
    int m, k, i, j, t1 ,t2, u, v;
    LL v1, v2;
    while(scanf("%d",&m)!=EOF)
    {
        memset(mat[0].ma,0,sizeof(mat[0].ma));
        n=0;
        while(m--)
        {
            scanf("%d%d",&u,&v);
            int f1=find1(u);
            if(f1<0)
            {
                q[n++]=u;
                f1=n-1;
            }
            int f2=find1(v);
            if(f2<0)
            {
                q[n++]=v;
                f2=n-1;
            }
            mat[0].ma[f1][f2]++;
        }
        scanf("%d",&k);
        Pow();
        while(k--)
        {
            scanf("%I64d%I64d%d%d",&v1,&v2,&t1,&t2);
            int f1=find1(v1);
            int f2=find1(v2);
            if(f1<0||f2<0)
            {
                puts("0");
                continue ;
            }
            int ans=0;
            for(i=t1-1; i<t2; i++)
            {
                if(i==-1) continue ;
                ans+=mat[i].ma[f1][f2]%mod;
                ans%=mod;
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}


HDU 2254 奥运(矩阵)