您的位置:首页 > 其它

【已解决】zoj 3497 Mistwald 矩阵快速幂

2011-04-29 19:57 405 查看
时隔几个月重新做,终于ac了!

题目看似是图论,但事实是矩阵相乘。根据离散数学书上说的,邻接矩阵A的k次幂得到的新矩阵B中,bij表示ai到aj长度为k的通路数。

上面的方法计算的是任意两点通路数,而本题目要求终点不能有出边,基于酱紫,只要把终点那一行全部置为0就ok,这里不求通路数,改为求能否k步到达终点。

#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <time.h>
#include <cstdio>
#include <math.h>
#include <iomanip>
#include <cstdlib>
#include <limits.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;

#define LL long long
#define MIN INT_MIN
#define MAX INT_MAX
#define PI acos(-1.0)
#define FRE freopen("input.txt","r",stdin)
#define FF freopen("output.txt","w",stdout)
int N,M,T;
typedef struct node
{
int mat[30][30];
}Mat;
Mat unit,init;
void Init()
{
char c;
scanf("%d%d",&N,&M);
getchar();
int i,j,x1,y1,x2,y2,x3,y3,x4,y4;
memset(init.mat,0,sizeof(init.mat));//每次清零!
for(i=1; i<=N; i++)
for(j=1; j<=M; j++)
{
scanf("((%d,%d),(%d,%d),(%d,%d),(%d,%d))",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
getchar();
if ((i-1)*M+j == N*M) continue;//舍掉终点的出边
init.mat[(i-1)*M+j][(x1-1)*M+y1]=1;
init.mat[(i-1)*M+j][(x2-1)*M+y2]=1;
init.mat[(i-1)*M+j][(x3-1)*M+y3]=1;
init.mat[(i-1)*M+j][(x4-1)*M+y4]=1;
unit.mat[(i-1)*M+j][(i-1)*M+j]=1;
}
}
Mat mul(Mat a,Mat b)
{
int i,j,k;
Mat c;
for(i=1;i<=T;i++)
for(j=1;j<=T;j++)
{
c.mat[i][j]=0;
for(k=1;k<=T;k++)//一开始忘记了终点不能重复走,使到k==T
c.mat[i][j] = c.mat[i][j]| (a.mat[i][k]&b.mat[k][j]);
}
return c;
}

Mat cal(int k)//矩阵二分快速幂
{
Mat i=init,ans=unit;
while (k) {
if (k&1)
ans=mul(ans,i);
i=mul(i,i);
k>>=1;
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
bool ok = 0;
while(t--)
{
Init();//input
T=N*M;
int num,q;
scanf("%d",&num);
//if (ok) puts("");
ok = 1;
int i;
while(num--)
{
scanf("%d",&q);
Mat r=cal(q);
if(r.mat[1][T]==0)
printf("False\n");
else
{
for(i=1;i<=T;i++)
{
if(r.mat[1][i])
break;
}
if(i == T)
printf("True\n");
else printf("Maybe\n");
}
}
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: