HDU 4725 The Shortest Path in Nya Graph(堆优化dijkstra)

来源:互联网 发布:淘宝免单红包怎么抽取 编辑:程序博客网 时间:2024/06/05 08:29

题目链接:【HDU 4725】

n个点分布在n层上,同一层内任意点之间的花费是0,从第i层的任意一个点到第i+1层的任意一个点需要花费c,m条路径,每条路径包括u、v、w,表示在点u,v之间来回需要花费w,问能否从从点1走到到点n,能的话输出最小花费,不能的话就输出-1

将一层看做两个点,第i层对应n+2*i-1、n+2*i,一个点是出去的,一个点是进来的

举个例子:

一共是3个点,即n=3,第3个点在第二层上,建图的时候就是 3 ==> 6 &&7 ==> 3,并且点3跟点6之间的花费是0,点7跟点3之间的花费也是0

然后将第i层与第i+1层连起来,他们之间的花费是c,也就是第i层出去的点指向第i+1层进来的点,第i层进来的点指向第i+1层出去的点,接下来就是堆优化的dijkstra

每一层为什么不转化为1个点的原因:每一层如果都是转化为一个点,那实际存在的点与层转化过来的点之间就是双向的,而不是单向的,这样建图会出问题的,比如点1和点2都在层5上,会出现图中的情况,点1到点2的最终花费会变成0

             

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <string>#include <queue>#include <vector>using namespace std;const int inf=1e5+10;const int maxn=0x3f3f3f3f;int t, n, m, c, p, cas;struct node{int v, w;node(int vi, int wi) : v(vi), w(wi) {}friend bool operator < (const node n1, const node n2){return n1.w>n2.w;}};vector<node>vec[inf*3];int vis[inf*3], dis[inf*3];void dij(){priority_queue<node>q;memset(dis, 0x3f3f3f3f, sizeof(dis));dis[1]=0;q.push(node(1,0));while(!q.empty()){node s=q.top();q.pop();int u = s.v, wi=s.w;if(vis[u]==cas) continue;vis[u] = cas;for(int i=0; i<vec[u].size(); i++){node e=vec[u][i];if(vis[e.v]!=cas && dis[e.v]>dis[u]+e.w){dis[e.v]=dis[u]+e.w;q.push(node(e.v, dis[e.v]));}}}}void add(int u, int v, int wi){vec[u].push_back(node(v, wi));}int main(){scanf("%d", &t);cas=1;while(t--){scanf("%d%d%d", &n, &m, &c);for(int i=1; i<=3*n; i++) vec[i].clear();for(int i=1; i<=n; i++)//层上的点与层之间的单向连接  {scanf("%d", &p);add(i, n+2*p-1,0);add(n+2*p, 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);}for(int i=0; i<m; i++){int u,v, wi;scanf("%d%d%d", &u, &v, &wi);add(u,v,wi);add(v,u,wi);} dij();int ans=dis[n];printf("Case #%d: %d\n", cas++, (ans==maxn ? -1:ans));}return 0;}



0 0
原创粉丝点击