HDU 4479 Shortest path 带限制最短路
题意:给定一个图,求从1到N的递增边权的最短路。
解法:类似于bellman-ford思想,将所有的边先按照权值排一个序,然后依次将边加入进去更新,
每条边只更新一次,为了保证得到的路径是边权递增的,每次将相同权值的边全部取出来一同更新,
每条边能够更新的前提是某一个端点在之前被更小的边权更新过。另外一个要注意的地方就是一次相同边的更新中,
要把所有的更新暂存起来最后一起去更新,这样是为了防止同一权值的边被多次加入到路径中去。
#include <iostream> #include <cstdio> #include <climits> #include <cstring> #include <queue> #include <algorithm> using namespace std; typedef __int64 LL; const LL maxn = 10005; const LL maxm = 50005; const LL INF = 0x3f3f3f3f3f3f3f3fLL; struct node{ int u,v,len; bool operator < (node a)const{ return len < a.len; } }edge[maxm]; LL dis[maxn]; int id,n,m; struct Rec{ int v; LL d; }rec[maxn]; void update(int l,int r){ int index = 0; for(int i = l; i <= r; i++){ int u = edge[i].u,v = edge[i].v,len = edge[i].len; if( dis[u] != INF && dis[v] > dis[u] + len ) rec[index].v = v,rec[index++].d = dis[u] + len; if( dis[v] != INF && dis[u] > dis[v] + len) rec[index].v = u,rec[index++].d = dis[v] + len; } for(int i = 0; i < index; i++) dis[rec[i].v] = min(dis[rec[i].v],rec[i].d); } void slove(){ memset(dis,0x3f,sizeof(dis)); cout << dis[0] << endl; dis[1] = 0; for(int i = 0,j; i < m; i = j){ for( j = i+1; j < m ;j ++) if( edge[i].len != edge[j].len) break; update(i,j-1); } } int main(){ int t; scanf("%d",&t); while( t-- ){ scanf("%d%d",&n,&m); for(int i = 0; i < m; i++) scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].len); sort(edge,edge+m); slove(); if( dis[n] == INF)puts("No answer"); else printf("%I64d\n",dis[n]); } return 0; }