题目
分析:题目大意即在一个无向图中,询问从起点到终点,走n步的最短路。最多100条边,所以最多100个点,对点进行离散化。用floyd求最短路,因为floyd就是向中间插点(插点法)所以只需要做n次floyd,同时使用倍增来加速。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAXM 100
int n,r[MAXM*2+1],u[MAXM*2+1],v[MAXM*2+1],wt[MAXM+1],m,s,t,nr;
typedef int matrix[MAXM+1][MAXM+1];
matrix ans;
void Read(int &x){
char c;
while(c=getchar(),c!=EOF)
if(c>='0'&&c<='9'){
x=c-'0';
while(c=getchar(),c>='0'&&c<='9')
x=x*10+c-'0';
ungetc(c,stdin);
return;
}
}
void read(){
Read(n),Read(m),Read(s),Read(t);
memset(ans,0x3f,sizeof ans);
int i;
for(i=1;i<=m;i++){
Read(wt[i]),Read(u[i]),Read(v[i]);
r[(i<<1)-1]=u[i],r[i<<1]=v[i];
}
sort(r+1,r+m*2+1);
nr=unique(r+1,r+m*2+1)-r-1;
for(i=1;i<=m;i++){
u[i]=lower_bound(r+1,r+nr+1,u[i])-r;
v[i]=lower_bound(r+1,r+nr+1,v[i])-r;
ans[u[i]][v[i]]=ans[v[i]][u[i]]=wt[i];
}
}
void floyd(matrix a,matrix b,matrix c){
int i,j,k;
matrix d;
memset(d,0x3f,sizeof d);
for(k=1;k<=nr;k++)
for(i=1;i<=nr;i++)
for(j=1;j<=nr;j++)
d[i][j]=min(d[i][j],a[i][k]+b[k][j]);
memcpy(c,d,sizeof d);
}
void quick_pow(matrix a,int b,matrix c){
matrix t,d;
memset(d,0x3f,sizeof d);
memcpy(t,a,sizeof t);
for(int i=1;i<=nr;i++)
d[i][i]=0;
while(b){
if(b&1)
floyd(d,t,d);
floyd(t,t,t);
b>>=1;
}
memcpy(c,d,sizeof d);
}
int main()
{
read();
quick_pow(ans,n,ans);
printf("%d\n",ans[lower_bound(r+1,r+nr+1,s)-r][lower_bound(r+1,r+nr+1,t)-r]);
}