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; }