【BZOJ1706】[USACO2007 Nov] relays 奶牛接力跑(倍增Floyd)

点此看题面

大致题意:\(s\)\(t\)经过\(k\)条边的最短路。

倍增\(Floyd\)

一个奇怪的东西,矩乘它不香吗?

大致意思就是记\(f_{i,j,p}\)表示从\(i\)\(j\)经过\(2^p\)条边的最短路。

转移?\(Floyd\)会吧,倍增\(LCA\)的预处理会吧,两个合一合就好了。

懒得多说了,其实我觉得矩乘更好些

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 200
#define LN 20
#define INF 1e9
#define Gmin(x,y) (x>(y)&&(x=(y)))
using namespace std;
int m,k,s,t,w[N+5],u[N+5],v[N+5],dc,dv[N+5],ans[N+5][N+5][2],f[N+5][N+5][LN+5];
int main()
{
	RI i,j,g,x,y;scanf("%d%d%d%d",&k,&m,&s,&t),dv[1]=s,dv[dc=2]=t;
	for(i=1;i<=m;++i) scanf("%d%d%d",w+i,u+i,v+i),dv[++dc]=u[i],dv[++dc]=v[i];
	for(sort(dv+1,dv+dc+1),dc=unique(dv+1,dv+dc+1)-dv-1,i=1;i<=dc;++i)//离散化
		for(f[i][i][0]=INF,j=i+1;j<=dc;++j) f[i][j][0]=f[j][i][0]=ans[i][j][1]=ans[j][i][1]=INF;//预赋值为INF
	for(i=1;i<=m;++i) x=lower_bound(dv+1,dv+dc+1,u[i])-dv,
		y=lower_bound(dv+1,dv+dc+1,v[i])-dv,Gmin(f[x][y][0],w[i]),Gmin(f[y][x][0],w[i]);//初始化
	s=lower_bound(dv+1,dv+dc+1,s)-dv,t=lower_bound(dv+1,dv+dc+1,t)-dv;
	RI p;for(p=1;p<=LN;++p) for(i=1;i<=dc;++i) for(j=1;j<=dc;++j)//倍增Floyd
		for(f[i][j][p]=INF,g=1;g<=dc;++g) Gmin(f[i][j][p],f[i][g][p-1]+f[g][j][p-1]);
	for(p=0;p<=LN;++p) if((k>>p)&1)//枚举二进制下每一位
	{
		for(i=1;i<=dc;++i) for(j=1;j<=dc;++j) ans[i][j][0]=ans[i][j][1],ans[i][j][1]=INF;//滚存
		for(i=1;i<=dc;++i) for(j=1;j<=dc;++j)//转移
			for(g=1;g<=dc;++g) Gmin(ans[i][j][1],ans[i][g][0]+f[g][j][p]);
	}return printf("%d\n",ans[s][t][1]),0;//输出答案
}
posted @ 2020-06-08 19:38  TheLostWeak  阅读(48)  评论(0编辑  收藏