hdu 4725 带层的最短路
题意:n个点,m条边,以及相邻层之间移动的代价c,给出每个点所在的层数,以及m条边,
每条边有u,v,c,表示从节点u到v(无向),并且移动的代价 c ,问说从 1 到 n 的代价最小是多少。
参考 https://www.cnblogs.com/kuangbin/archive/2013/09/11/3315071.html
思路:
最短路。主要是建图。
N个点,然后有N层,要增加2*N个点。总共是3*N个点。
点1~N就是对应的实际的点1~N. 要求的就是1到N的最短路。
然后点N+1 ~ 3*N 是N层拆出出来的点。
第i层,入边到N+2*i-1, 出边从N+2*i 出来。(1<= i <= N)
N + 2*i 到 N + 2*(i+1)-1 加边长度为C. 表示从第i层到第j层。
N + 2*(i+1) 到 N + 2*i - 1 加边长度为C,表示第i+1层到第j层。
如果点i属于第u层,那么加边 i -> N + 2*u -1 N + 2*u ->i 长度都为0
就是说 点 x 与之对应的层点有2个, 到一个 a 入度为1,权值为0 ,一个 b 出度为1 权值为 0
由于层之间的移动, 假设y对应层和他是相邻的, 那么c,d 需要添加 a->d 和 c->b 两个边
来表示于 x->a->d->y y->c->b->a... 这样最短路也要是3*n 了
#include<cstdio> #include<iostream> #include<queue> #include<cstring> #include<cmath> using namespace std; #define ll long long #define pb push_back #define fi first #define se second #define pii pair<int,int> #define mp make_pair const int N = 3e5+4; const int INF = 1e9+3; //https://www.cnblogs.com/kuangbin/archive/2013/09/11/3315071.html struct node{ int to,cost; }; vector<node>V[N]; int d[N]; int n,m,c; void add(int u,int v,int c){ V[u].pb( node{v,c}); } void dij(){ for(int i=1;i<=n;++i)d[i]=INF; d[1]=0; priority_queue< pii , vector<pii> ,greater<pii> > Q; Q.push(mp(0,1)); while(!Q.empty()){ pii p =Q.top();Q.pop(); int v= p.se;int val =p.fi; if(val>d[v])continue; for(int i=0;i<V[v].size();++i){ node e= V[v][i]; int u = e.to; if(d[u] > d[v]+e.cost){ d[u] = d[v]+e.cost; Q.push(mp(d[u],u)); } } } } int main(){ int t; cin>>t; int cnt=1; while(t--){ scanf("%d %d %d",&n,&m,&c); for(int i=1;i<=n*3;++i)V[i].clear(); for(int i=1;i<=n;++i){ int l; scanf("%d",&l); add(i,n+2*l-1,0); add(n+2*l,i,0); } for(int i=1;i<n;++i){ add( n+2*i-1,n+2*(i+1),c ); add(n +2*(i+1)-1 , n+2*i,c); } while(m--){ int u,v,d; scanf("%d %d %d",&u,&v,&d); add(u,v,d); add(v,u,d); } n*=3; dij(); n/=3; printf("Case #%d: ",cnt++); if(d[n]==INF)printf("-1\n"); else cout<<d[n]<<endl; } return 0; }