题目链接:
其实这两道题基本上是一样的,就是分层图的套路题。
为什么是分层图呢?首先,我们的选择次数比较少,可以把这几层的图建出来而不会爆空间。然后因为选择一个边权为0的路线之后我们就进入了下一个状态,最短路的计算就和不选择这个边权为0的路线完全独立了。
所以我们把每一层的图建出来,相邻图有边的话连0边,其他的按照原样连。dis数组存最短路。\(最后答案就是dis[n*k+end]\),end为终点。
所以所以。。。也没有什么可说的???
注意要写dij,以后图论的题能不写spfa就别写。
#include#include #include #include #include #include #include #define MAXM 4100000#define MAXN 410000using namespace std;bool done[MAXN];int n,m,edge_number,st,end,k;int dis[MAXN],head[MAXN];struct Edge{int nxt,to,dis;}edge[MAXM];struct Node{ int u,d; friend bool operator <(struct Node x,struct Node y) { return x.d>y.d; }};void add(int from,int to,int dis){ edge[++edge_number].dis=dis; edge[edge_number].to=to; edge[edge_number].nxt=head[from]; head[from]=edge_number;}inline void dij(){ priority_queue q; memset(dis,0x3f,sizeof(dis)); q.push((Node){st,0}); dis[st]=0; while(!q.empty()) { int u=q.top().u; q.pop(); if(done[u]) continue; done[u]=1; for(int i=head[u];i;i=edge[i].nxt) { int v=edge[i].to; if(dis[v]>dis[u]+edge[i].dis) { dis[v]=dis[u]+edge[i].dis; q.push((Node){v,dis[v]}); } } }}int main(){ scanf("%d%d%d",&n,&m,&k); st=1,end=n; for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); for(int j=1;j<=k;j++) { add(u+(j-1)*n,v+j*n,0); add(v+(j-1)*n,u+j*n,0); add(u+j*n,v+j*n,w); add(v+j*n,u+j*n,w); } } for(int i=1;i<=k;i++) add((i-1)*n+end,i*n+end,0); dij(); printf("%d\n",dis[n*k+end]); return 0;}