现在的位置: 首页 > 综合 > 正文

hdu shortest path 快速矩阵比较 + 最短路

2018年04月25日 ⁄ 综合 ⁄ 共 1527字 ⁄ 字号 评论关闭

这货就是个坑啊,80^5次方都可以过,数据太水了把。。。

快速矩阵比较:

就是把一个矩阵乘上一个{1,2,3,。。。。m}的向量,得到的矩阵叫做比较阵

这样能顺利把比较的复杂度降到o(n),不过需要注意的两个比较阵相同,不一定意味着两个原来的矩阵一定相同

这个就和hash一样,是有碰撞的,这个原理也就是hash,要是没有碰撞的话,得用80进制,太大了,存不下。

就是这个hash碰撞概率比较小而已,要找到碰撞的话还是很容易的

http://acm.hdu.edu.cn/showproblem.php?pid=2807

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int MAXN=80+10;
int n,m;
struct Matrix
{
    int v[MAXN][MAXN],c[MAXN];
    void cal()
    {
        memset(c,0,sizeof(c));
        for(int j=0; j<m; j++)
            for(int i=0; i<m; i++)
            {
                c[i]+=v[i][j]*(i+1);
            }
    }
    void init()
    {
        memset(v,0,sizeof(v));
    }
    void readin()
    {
        for(int i=0; i<m; i++)
            for(int j =0; j<m; j++)
                scanf("%d",&v[i][j]);
        cal();
    }
    bool operator ==(const Matrix &a) const
    {
        for(int i=0; i<m; i++)
                if(c[i]!=a.c[i])
                    return false;
        return true;
    }
    Matrix operator *(const Matrix &a) const
    {
        Matrix ans;
        ans.init();
        for(int i=0; i<m; i++)
            for(int k=0; k<m; k++)
                if(v[i][k])
                    for(int j=0; j<m; j++)
                        ans.v[i][j]+=v[i][k]*a.v[k][j];
        ans.cal();
        return ans;
    }
};
int G[MAXN][MAXN];
Matrix a[MAXN];
int main()
{
//    freopen("in","r",stdin);
    int INF;
//    cout<<pow(80,80)<<endl;
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0 && m==0 )break;
        memset(G,0x3f,sizeof(G));
        INF=G[0][0];
        for(int i=0; i<n; i++)
            a[i].readin();
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n; j++)
            {
                if(i==j) continue;
                Matrix ret=a[i]*a[j];
                for(int k=0; k<n; k++)
                {
                    if(k==i || k==j) continue;
                    if(ret==a[k])
                        G[i][k]=1;
                }
            }
        }
        for(int i=0; i<n; i++) G[i][i]=0;
        for(int k=0; k<n; k++)
            for(int i=0; i<n; i++)
                for(int j=0; j<n; j++)
                    G[i][j]=min(G[i][j],G[i][k]+G[k][j]);

        int q;
        scanf("%d",&q);
        while(q--)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            u--,v--;
            int ans=G[u][v];
            if(ans>=INF)
                puts("Sorry");
            else
                printf("%d\n",ans);
        }
    }
    return 0;
}

抱歉!评论已关闭.