题意:给一个有向图,不同时间有不同的边权(共八种),求最短路径。
思路:把一个点拆成8个,上下差一秒的相连,spfa求最短路。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=6000006;
const int inf =1<<30;
struct data{
int u,v,w,nxt;
}e[maxn];
int n,m,cnt=0,ans=inf;
int c[9][9],b[maxn][9],fst[maxn];
inline int get(){
char c;while(!isdigit(c=getchar()));
int v=c-48;while(isdigit(c=getchar()))v=v*10+c-48;
return v;
}
inline void add(int x,int y,int z){
e[++cnt].u=x;e[cnt].v=y;e[cnt].w=z;e[cnt].nxt=fst[x],fst[x]=cnt;
}
bool vis[maxn];
int dis[maxn];
queue<int>q;
inline void spfa(){
for(int i=2;i<=8*n;++i)dis[i]=inf;
memset(vis,0,sizeof(vis));
q.push(1);vis[1]=1;dis[1]=0;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=fst[x];i;i=e[i].nxt){
int y=e[i].v;
if(dis[y]>dis[x]+e[i].w){
dis[y]=dis[x]+e[i].w;
if(!vis[y])q.push(y),vis[y]=1;
}
}
vis[x]=0;
}
for(int i=1;i<=8;++i)ans=min(ans,dis[(n-1)*8+i]);
printf("%d\n",ans);
}
int main(){
n=get();m=get();
for(int i=1;i<=8;++i)for(int j=1;j<=8;++j)c[i][j]=get();
for(int i=1;i<=n;++i)for(int j=1;j<=8;++j)b[i][j]=get();
for(int i=1;i<=m;++i){
int x=get(),y=get(),z=get();
for(int j=1;j<=8;++j)add((x-1)*8+j,(y-1)*8+(j%8)+1,z+c[b[x][j]][b[y][j]])/*,printf("%d %d %d\n",e[cnt].u,e[cnt].v,e[cnt].w);*/;
}
spfa();
return 0;
}