poj3613 奇特的矩阵乘法

来源:互联网 发布:淘宝网皮草女款 编辑:程序博客网 时间:2024/04/26 11:12

  


       题目大意很简单:给出一个无向图,求两个点之间的经过k条边的最短路(边可以重复经过)

      最多只有100条边,但是k高达10^6。


      可以用 类bellman ford的方法,将边迭代n次

       (与bellman ford不同的是,每一次迭代都必须选边,不过spfa无法保证每一条边都取);

      这样的复杂的事o(ne)的 ,已经有10^8,而且中间还涉及大量的数组滚动,要ac还是太难了。


     于是,一种奇异的算法出现了——矩阵乘法;

     如果我们用邻接矩阵存好走k条边的距离之后,与贮存了边的邻接矩阵相称,得到的矩阵就是走k+1条边的距离,

     只要把这里的矩阵相乘的方式改为——a[ i , j ]:=min(b [ i,k]+b [ k , j ]),即乘法改为加法,加法改为取min

      由于加法和min满足结合率,可以直接快速幂了,复杂度是100^3 * log(10^6).

    

     

   

program lmd;var    i,j,k,n,maxn,x,y,z,t,s,e:longint;    mul,now,ans:array[1..1000,1..1000]of longint;    hash:array[1..1000]of longint;    yes:array[1..1000]of boolean;    a:array[0..100+5]of record                 x,y,z:longint;                 end;begin    assign(input,'3613.in');    assign(output,'3613.out');    reset(input);rewrite(output);     read(n,t,s,e);     fillchar(yes,sizeof(yes),false);     maxn:=0;     for i:=1 to t do      begin        read(a[i].z,a[i].x,a[i].y);        yes[a[i].x]:=true;        yes[a[i].y]:=true;      end;     maxn:=0;     for i:=1 to 1000 do       if yes[i] then         begin           inc(maxn);           hash[i]:= maxn;         end;     for i:=1 to maxn do      for j:=1 to maxn do        begin         mul[i,j]:=maxlongint shr 1;         ans[i,j]:=maxlongint shr 1;        end;     for i:=1 to t do       begin          mul[hash[a[i].x],hash[a[i].y]]:=a[i].z;          mul[hash[a[i].y],hash[a[i].x]]:=a[i].z;       end;     for i:=1 to maxn do       ans[i,i]:=0;     while n>0 do      begin         if n and 1=1 then          begin           for i:=1 to maxn do             for j:=1 to maxn do              begin               now[i,j]:=ans[i,j];               ans[i,j]:=maxlongint shr 1;              end;           for i:=1 to maxn do             for j:=1 to maxn do               for k:=1 to maxn do                 if ans[i,j]>now[i,k]+mul[k,j] then                     ans[i,j]:=now[i,k]+mul[k,j];           end;         for i:=1 to maxn do            for j:=1 to maxn do              now[i,j]:=maxlongint shr 1;         for i:=1 to maxn do           for j:=1 to maxn do             for k:=1 to maxn do             if now[i,j]>mul[i,k]+mul[k,j] then                now[i,j]:=mul[i,k]+mul[k,j];         for i:=1 to maxn do          for j:=1 to maxn do             mul[i,j]:=now[i,j];         n:=n shr 1;      end;    write(ans[hash[s],hash[e]]);    close(input);close(output);end.                        

原创粉丝点击