这道题目把矩阵跟图论完美地结合在了一起,矩阵与图论,本来就是难舍难分。能一下子想到相关知识,还是比较有难度

要看多点书嘞。

/*
*题目大意:
*        他知道中国有很多的名胜古迹,他知道自己在t1 到 t2天内不可能把所有的
*        地方都玩遍,所以他决定指定两个地方v1,v2,如果参赛员能计算出在t1到t2天
*        (包括t1,t2)内从v1到v2共有多少种走法(每条道路走需要花一天的时间,且不
*        能在某个城市停留,且t1=0时的走法数为0),那么他就会获得相应数量的金牌,
*        城市的总数<=30,两个城市间可以有多条道路,每条都视为是不同的。
*解题思路:
*        以每两个点之间路径的数量建立邻接矩阵A,然后邻接矩阵的l次幂就代表两个点之间
*        路径长度为l的数量。而当算A^1 + A^2 + A^3 + A^4 + …… + A^l时,就代表邻接矩阵
*        中任意两点的长度为1~l的数量。来到这里,就足够解决该题了。
*/
View Code
  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <map>
  5 
  6 #define MAX_DIMENSION 31 
  7 
  8 using namespace std;
  9 
 10 typedef int MATRIX_TYPE;
 11 typedef int MAX_INT_TYPE; 
 12 typedef MATRIX_TYPE Matrix[MAX_DIMENSION][MAX_DIMENSION];
 13 int ndim=MAX_DIMENSION;
 14 int mod = 2008;
 15 
 16 void m_zero(Matrix  x)
 17 {
 18     memset(x, 0, sizeof(MATRIX_TYPE)*MAX_DIMENSION*MAX_DIMENSION);
 19 }
 20 
 21 void m_one(Matrix  x)
 22 {
 23     int i;
 24     m_zero(x);
 25     for(i=0;i<ndim;++i)x[i][i]=1;
 26 }
 27 
 28 void m_copy(Matrix  src,Matrix  dest)
 29 {
 30     memcpy(dest,src, sizeof(MATRIX_TYPE)*MAX_DIMENSION*MAX_DIMENSION);
 31 }
 32 
 33 //z=x+y;
 34 void m_add(Matrix  x,Matrix  y,Matrix  z)
 35 {
 36     int i,j;
 37     for(i=0;i<ndim;i++)
 38         for(j=0;j<ndim;j++)
 39             if(mod<=1)z[i][j]=x[i][j]+y[i][j];
 40             else z[i][j]=(x[i][j]+(MAX_INT_TYPE)y[i][j])%mod;//module
 41 }
 42 
 43 
 44 //c=a*b
 45 void m_multiple(Matrix  a,Matrix b,Matrix c)
 46 {
 47     int i,j,k;
 48     MAX_INT_TYPE t;
 49 
 50     for(i=0;i<ndim;i++)
 51         for(j=0;j<ndim;j++)
 52         {
 53             t=0;
 54             if(mod<=1)
 55                 for(k=0;k<ndim;k++) t+=a[i][k]*b[k][j];//module
 56             else
 57                 for(k=0;k<ndim;k++){
 58                     t+=(a[i][k]*(MAX_INT_TYPE)b[k][j])%mod;
 59                     t%=mod;
 60                 }//module
 61             c[i][j]=t;
 62         }
 63 }
 64 
 65 //根据已经算出来的x^1 x^2 x^4 ...去求矩阵的幂y=x^n
 66 void m_pow_with_saved(Matrix  x_p[],unsigned int n, Matrix y)
 67 {
 68     Matrix temp;
 69     m_one(y);
 70     for(int k=1;n;++k,n>>=1)
 71     {
 72         if ((n & 1) != 0)
 73         {
 74             m_multiple(x_p[k],y,temp);
 75             m_copy(temp,y);
 76         }
 77     }
 78 }
 79 
 80 //计算根据已经算出来的x^1 x^2 x^4 ...去求矩阵的幂和y=sum(x^n)
 81 void m_pow_sum1(Matrix  x_p[],unsigned int n, Matrix y)
 82 {
 83     m_zero(y);
 84     if(n==0)return;
 85     if(n==1) m_copy(x_p[1],y);
 86     else
 87     {
 88         Matrix temp;
 89         //calculate x^1+...+^(n/2)
 90         m_pow_sum1(x_p,n>>1,temp);
 91         //add to y
 92         m_add(temp,y,y);
 93         //calculate x^(1+n/2)+...+x^n
 94         Matrix temp2;
 95         m_pow_with_saved(x_p,n>>1,temp2);
 96         Matrix temp3;
 97         m_multiple(temp,temp2,temp3);
 98         //add to y
 99         m_add(temp3,y,y);
100         if(n&1)
101         {
102             //calculate x^(n-1)
103             m_multiple(temp2,temp2,temp3);
104             //calculate x^n
105             m_multiple(temp3,x_p[1],temp2);
106             //add x^n
107             m_add(temp2,y,y);
108         }
109     }
110 
111 }
112 
113 //计算x^1 x^2 x^4 ...,然后调用求幂和的地方
114 void m_pow_sum(Matrix x, unsigned int n, Matrix y)
115 {
116     //calculate x^1 x^2 x^4 ... x^logn
117     unsigned int i=0,logn,n2=n;
118     for(logn=0,n2=n;n2;logn++,n2 >>= 1);
119     Matrix *pow_arry=new Matrix[logn==0?2:(logn+1)];
120     m_one(pow_arry[0]);
121     m_copy(x,pow_arry[1]);
122     for(i=1;i<logn;i++)
123     {
124         m_multiple(pow_arry[i],pow_arry[i],pow_arry[i+1]);
125     }
126 
127     m_pow_sum1(pow_arry,n,y);
128     delete []pow_arry;
129 }
130 
131 int main(void)
132 {
133 #ifndef ONLINE_JUDGE
134     freopen("in.txt", "r", stdin);
135 #endif
136 
137     map<int, int> index;
138     int n;
139     while(scanf("%d", &n) == 1)
140     {
141         index.clear();
142         int ind = 0;
143         Matrix a;
144         m_zero(a);
145         for(int i = 0; i < n; i++)
146         {
147             int u, v;
148             scanf("%d %d", &u, &v);
149             if(!index.count(u))
150                 index[u] = ind++;
151             if(!index.count(v))
152                 index[v] = ind++;
153             a[index[u]][index[v]]++;
154         }
155         ndim = ind;
156 
157         int m;
158         scanf("%d", &m);
159         for(int i = 0; i < m; i++)
160         {
161             int u, v, t1, t2;
162             scanf("%d %d %d %d", &u, &v, &t1, &t2);
163             //防止u,v未出现过。
164             if(!index.count(u) || !index.count(v))
165             {
166                 printf("0\n");
167                 continue;
168             }
169             u = index[u], v = index[v];
170             if(t1 > t2)
171             {
172                 t1 = t1 ^ t2;
173                 t2 = t1 ^ t2;
174                 t1 = t1 ^ t2;
175             }
176             if(!t2)
177             {
178                 printf("0\n");
179                 continue;
180             }
181             Matrix presum, tolsum;
182             if(t1 > 1)
183             {
184                 m_pow_sum(a, t1 - 1, presum);
185                 m_pow_sum(a, t2, tolsum);
186                 printf("%d\n", ((tolsum[u][v] - presum[u][v]) % mod + mod) % mod);
187             }
188             else
189             {
190                 m_pow_sum(a, t2, tolsum);
191                 printf("%d\n", ((tolsum[u][v] % mod) + mod) % mod);
192             }
193         }
194     }
195     return 0;
196 }
posted on 2012-08-02 10:40  cchun  阅读(226)  评论(0编辑  收藏  举报