hdu 2254 奥运

来源:互联网 发布:java培训骗局 编辑:程序博客网 时间:2024/04/26 00:07

点击打开hdu 2254

思路: 矩阵乘法

分析:

1 题目给定一个有向图,要求t1-t2天内v1-v2的路径的个数

2 假设有向图的邻接矩阵为A,那么A表示的是有向图中走一步能够到达哪些点的方案数,那么A^n表示的是走n步能够到达哪些点的方案数

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

3 还有点的范围很大,边数很少,所以我们应该要进行离散化

4 但是数据量很大,对于具体的一组我们应该要事先求出具体的每一个矩阵,然后直接使用即可


代码:

/************************************************ * By: chenguolin                               *  * Date: 2013-08-25                             * * Address: http://blog.csdn.net/chenguolinblog * ***********************************************/#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef __int64 int64;const int MOD = 2008;const int MAXN = 10000;const int N = 30;int n , pos;int64 num[2*MAXN];struct Edge{    int64 x;    int64 y;};Edge e[MAXN];struct Matrix{    int mat[N][N];    Matrix operator*(const Matrix& m)const{        Matrix tmp;        for(int i = 0 ; i < pos ; i++){            for(int j = 0 ; j < pos ; j++){                tmp.mat[i][j] = 0;                for(int k = 0 ; k < pos ; k++){                    tmp.mat[i][j] += mat[i][k]*m.mat[k][j]%MOD;                    tmp.mat[i][j] %= MOD;                }            }        }        return tmp;    }};Matrix ma[MAXN];int search(int64 x){    int left = 0;    int right = pos-1;    while(left <= right){        int mid = (left+right)>>1;        if(num[mid] == x)            return mid;        else if(num[mid] < x)            left = mid+1;        else            right = mid-1;    }    return -1;}void init(Matrix &m){    memset(m.mat , 0 , sizeof(m.mat));    sort(num , num+pos);    pos = unique(num , num+pos)-num;    for(int i = 0 ; i < n ; i++){        int x = search(e[i].x);        int y = search(e[i].y);        m.mat[x][y]++;    }}void Pow(Matrix m){    ma[0] = m;    for(int i = 1 ; i < MAXN ; i++)        ma[i] = ma[i-1]*m; }void solve(){    Matrix m;    init(m);    Pow(m);    int64 v1 , v2;    int k , t1 , t2;    scanf("%d" , &k);    while(k--){        scanf("%I64d%I64d%d%d" , &v1 , &v2 , &t1 , &t2);         if(t1 > t2 || t2 == 0){            puts("0");            continue;        }        int x = search(v1);         int y = search(v2);         if(x == -1 || y == -1){            puts("0");            continue;        }        int sum = 0;        for(int i = t1-1 ; i < t2 ; i++){            sum += ma[i].mat[x][y]%MOD;            sum %= MOD;        }        printf("%d\n" , sum);    }}int main(){    while(scanf("%d" , &n) != EOF){        pos = 0;         for(int i = 0 ; i < n ; i++){            scanf("%I64d%I64d" , &e[i].x , &e[i].y);            num[pos++] = e[i].x;            num[pos++] = e[i].y;        }        solve();    }    return 0;}


原创粉丝点击