poj 3613 Cow Relays (floyd+矩阵快速幂+坐标离散化)

来源:互联网 发布:拍大师软件下载 编辑:程序博客网 时间:2024/06/05 08:58

题意:求n条边中从起点经过T条边到终点的最短路。


算法:

n次floyd,用矩阵快速幂加速。

由于边只有100,点太多有1000,要离散化。


(     o(╯□╰)o       蒟蒻重新理解了floyd的矩阵变换,学习了矩阵快速幂   )


#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;int len[110],a[110],b[110],c;int s[110],n;bool vis[1010];struct Matrix{    int mp[110][110];    Matrix operator * (Matrix a)  //重载乘法运算符    {        Matrix tmp;        memset(tmp.mp,0,sizeof(tmp.mp));        for(int i=0;i<c;i++)   //floyd矩阵变换        {            for(int j=0;j<c;j++)  //这里三个循环都是从0-c(c-1为s[]元素的个数)            {                for(int k=0;k<c;k++)                {                    if(mp[i][k]!=0 && a.mp[k][j]!=0)                    {                        if(tmp.mp[i][j]==0 || tmp.mp[i][j]>mp[i][k]+a.mp[k][j])                            tmp.mp[i][j] = mp[i][k] + a.mp[k][j];                    }                }            }        }        return tmp;    }};int find(int x)   //查找离散化后的编号{    int l=0,r=c-1,mid;    while(l<=r)    {        mid = (l+r)>>1;        if(s[mid]==x) return mid;        else if(s[mid]>x) r = mid-1;        else l = mid+1;    }}Matrix fun(Matrix m,int k){    Matrix p = m,ans;    int flag = 1;    while(k)    {        if(k&1)        {            if(flag)   //flag为标记变量,k第一次为奇数时,是将p直接赋值给ans            {             //避免引入单位矩阵和p相乘                ans = p;                flag = 0;            }            else                ans = ans*p;        }        p = p*p;        k>>=1;    }    return ans;}int main(){    int t,st,ed;    while(scanf("%d%d%d%d",&n,&t,&st,&ed)!=EOF)    {        c = 0;        memset(vis,0,sizeof(vis));        for(int i=0;i<t;i++)        {            scanf("%d%d%d",&len[i],&a[i],&b[i]);            vis[a[i]] = true;            vis[b[i]] = true;        }        for(int i=1;i<=1000;i++)   //点太多,边只有100,离散化        {            if(vis[i]) s[c++] = i;        }        Matrix m1,m2;        memset(m1.mp,0,sizeof(m1.mp));        for(int i=0;i<t;i++)        {            int id1 = find(a[i]);   //离散化后的编号构图            int id2 = find(b[i]);            m1.mp[id1][id2] = m1.mp[id2][id1] = len[i];        }        m2 = fun(m1,n);   //矩阵快速幂求m1^n        printf("%d\n",m2.mp[find(st)][find(ed)]);    }    return 0;}



0 0