BZOJ 1706

题解:

倍增+floyd

首先这题比较容易想到是把每个点拆点做dij

但是这样复杂度是knlogn的

这道题的k较大,所以不行

我们考虑到每走一步,其实就是在进行一次floyd

而这个可以看成矩阵乘法

所以可以倍增优化

这样是logk*n^3的

 代码:

 

#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x&(-x))
#define IL inline
#define rint register int
#define me(x) memset(x,0,sizeof(x))
#define fi first
#define se second
#define mid ((h+t)/2) 
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
#define setit set<int>::iterator
const int INF=1e9;
char ss[1<<24],*A=ss,*B=ss;
IL char gc()
{
  return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++; 
}
template<class T>void read(T &x)
{
  rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=c^48;
  while (c=gc(),47<c&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;
}
int n,m,s,t,cnt;
struct re{
  int d[305][305];
}ys;
re js(re x,re y)
{
  re ans;
  rep(i,1,300)
    rep(j,1,300)
      ans.d[i][j]=INF;
  rep(k,1,cnt)
    rep(i,1,cnt)
      rep(j,1,cnt)
        ans.d[i][j]=min(ans.d[i][j],x.d[i][k]+y.d[k][j]);
  return(ans); 
}
re qpow(int x)
{
  if (x==1) return(ys);
  re y=qpow(x/2);
  y=js(y,y);
  if (x%2) y=js(y,ys);
  return(y);
}
int main()
{
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  read(n); read(m); read(s); read(t);
  rep(i,1,300)
    rep(j,1,300)
      ys.d[i][j]=INF;
  map<int,int>M;
  rep(i,1,m)
  {
    int x,y,z;
    read(x); read(y); read(z);
    int x1,x2;
    if (!M[y]) x1=M[y]=++cnt; else x1=M[y];
    if (!M[z]) x2=M[z]=++cnt; else x2=M[z];
    ys.d[x1][x2]=min(ys.d[x1][x2],x);
    ys.d[x2][x1]=min(ys.d[x2][x1],x);
  }
  re ans=qpow(n);
  printf("%d",ans.d[M[s]][M[t]]);
  return 0; 
}

 

posted @ 2018-06-18 15:48  尹吴潇  阅读(184)  评论(0编辑  收藏  举报