#include <iostream> #include <cstring> using namespace std; const int maxn=510; const int inf=10000; struct node { int type,len;//type为类型,len为道路长度 }map[maxn][maxn]; bool vis[maxn];//标记当前节点是否来过 void fiset(int n)//初始化数组 { for(int i=0;i<=n;i++) { for(int j=0;j<=n;j++) { map[i][j].len=inf; } vis[i]=0; } return ; } int dou(int x)//计算x的平方 { return x*x; } int dij(int n)//迪杰斯特拉算法 { int dist[maxn],small[maxn];//small数组记录到当前节点连续走过的小道长度 for(int i=1;i<=n;i++) { if(map[1][i].type==0) { small[i]=0; dist[i]=map[1][i].len; } else { small[i]=map[1][i].len; dist[i]=dou(map[1][i].len); } } vis[1]=1; for(int i=2;i<=n;i++) { int minn=inf,u; for(int j=1;j<=n;j++) { if(!vis[j]&&minn>dist[j]) { minn=dist[j]; u=j; } } vis[u]=1; for(int j=1;j<=n;j++) { if(vis[j])continue; if(map[u][j].type==0)//判断为大道,进行正常的松弛操作 { if(dist[u]+map[u][j].len<dist[j]) { small[j]=0; dist[j]=dist[u]+map[u][j].len; } } else//判断为小道则比较连续走小道的疲劳度再进行比较 { if(dist[j]>(dist[u]-dou(small[u])+dou(small[u]+map[u][j].len))) { small[j]=small[u]+map[u][j].len; dist[j]=dist[u]-dou(small[u])+dou(small[u]+map[u][j].len); } } } } return dist[n];//最终返回到达n点的最小疲劳度 } int main() { int n,m; int t,a,b,c; while(cin>>n>>m) { fiset(n); for(int i=0;i<m;i++) { map[i+1][i+1].len=0;//将节点到自身的长度初始化为0 cin>>t>>a>>b>>c; map[a][b].type=t; map[b][a].type=t; map[a][b].len=map[b][a].len=c; } cout<<dij(n)<<endl; } return 0; } /* 6 7 1 1 2 3 1 2 3 2 0 1 3 30 0 3 4 20 0 4 5 30 1 3 5 6 1 5 6 1 */