The Shortest Path in Nya Graph
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9374 Accepted Submission(s): 2073
Problem Description
This is a very easy problem, your task is just calculate el camino mas corto en un grafico, and just solo hay que cambiar un poco el algoritmo. If you do not understand a word of this paragraph, just move on.
The Nya graph is an undirected graph with "layers". Each node in the graph belongs to a layer, there are N nodes in total.
You can move from any node in layer x to any node in layer x + 1, with cost C, since the roads are bi-directional, moving from layer x + 1 to layer x is also allowed with the same cost.
Besides, there are M extra edges, each connecting a pair of node u and v, with cost w.
Help us calculate the shortest path from node 1 to node N.
The Nya graph is an undirected graph with "layers". Each node in the graph belongs to a layer, there are N nodes in total.
You can move from any node in layer x to any node in layer x + 1, with cost C, since the roads are bi-directional, moving from layer x + 1 to layer x is also allowed with the same cost.
Besides, there are M extra edges, each connecting a pair of node u and v, with cost w.
Help us calculate the shortest path from node 1 to node N.
Input
The first line has a number T (T <= 20) , indicating the number of test cases.
For each test case, first line has three numbers N, M (0 <= N, M <= 10 5) and C(1 <= C <= 10 3), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
The second line has N numbers l i (1 <= l i <= N), which is the layer of i th node belong to.
Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 10 4), which means there is an extra edge, connecting a pair of node u and v, with cost w.
For each test case, first line has three numbers N, M (0 <= N, M <= 10 5) and C(1 <= C <= 10 3), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
The second line has N numbers l i (1 <= l i <= N), which is the layer of i th node belong to.
Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 10 4), which means there is an extra edge, connecting a pair of node u and v, with cost w.
Output
For test case X, output "Case #X: " first, then output the minimum cost moving from node 1 to node N.
If there are no solutions, output -1.
If there are no solutions, output -1.
Sample Input
2 3 3 3 1 3 2 1 2 1 2 3 1 1 3 3 3 3 3 1 3 2 1 2 2 2 3 2 1 3 4
Sample Output
Case #1: 2 Case #2: 3
唉~~~~~~~ 难受
就是一道点与点之间的最短路
这道题主要分为两个部分,存点和dijkstra
因为如果按常规方法存为超时,所以要把点拆分来存(看网上百度到的)
因为是点与点之间的最短路所以可以用 :同一层的点之间的距离为零 ,相邻层的点距离为c
===================================
先把每一层的点指向本层 , 距离为零 点->层
在把每两个相邻层 用层指向点 层 -> 点
================================
这样就可以通过层为媒介把点指向点
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <algorithm> #include <iomanip> #include <cctype> #include <cmath> #include <stack> #include <queue> #include <vector> #include <cstdlib> #include <sstream> #include <set> #include <map> using namespace std; #define maxn 200010 const int INF=0x3f3f3f3f; struct ac{ int v,c; bool operator <(const ac &a)const{ return a.c<c; } }; vector<ac>que[maxn]; void add_edge(int u,int v,int c) { ac q; q.v=v; q.c=c; que[u].push_back(q); } int dis[maxn],flag[maxn]; int n,n1,m,c; void dijkstra() { memset(dis,INF,sizeof(dis)); memset(flag,0,sizeof(flag)); dis[1]=0; priority_queue<ac>qu; ac temp_1; temp_1.v=1; temp_1.c=0; qu.push(temp_1); while(!qu.empty()){ ac temp_2=qu.top(); qu.pop(); int v=temp_2.v; if(dis[v]<temp_2.c||flag[v])//temp_2.c的值有用到,所以下面必须更新 continue; if(v==n1) return ; flag[v]=1; for(int i=0;i<que[v].size();i++){ ac temp_3=que[v][i]; if(!flag[temp_3.v]&&dis[temp_3.v]>dis[v]+temp_3.c){ temp_3.c=dis[temp_3.v]=dis[v]+temp_3.c;//因为que是优先队列,所以如果要把temp_3入队,要把temp_3.c的值更新(挠头)一开始没想到,在大佬的帮助下,才改正。。 qu.push(temp_3); } } } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d %d %d",&n1,&m,&c); int a[maxn],vis[maxn]; memset(vis,0,sizeof(vis)); for(int j=1;j<=n1;j++){ scanf("%d",&a[j]);//a【j】表示j的点所在的层 vis[a[j]]=1; add_edge(n1+a[j],j,0);//层到点( 本层的点) } for(int j=1;j<=n1;j++){ if(a[j]+1<=n1&&vis[a[j]+1]&&vis[a[j]]){ add_edge(j,n1+a[j]+1,c); } //层+n指向的是层中的点 if(a[j]-1>=1&&vis[a[j]-1]&&vis[a[j]]){ add_edge(j,n1+a[j]-1,c);//这是层与层相连 } } //数据是点与点的短路最,所以点->层(上下的层),层->点(层中的点) for(int j=1;j<=m;j++){ int u,v,c; scanf("%d %d %d",&u,&v,&c); add_edge(u,v,c); add_edge(v,u,c); } dijkstra(); if(dis[n1]==INF) { dis[n1]=-1; } printf("Case #%d: %d\n",i,dis[n1]); for(int j=1;j<=2*n1;++j){//清空队列 que[j].clear(); } } return 0; }
迪杰斯特拉原代码
void dijkstra() { memset(dis,INF,sizeof(dis)); memset(flag,0,sizeof(flag)); dis[1]=0; for(int i=1;i<=n1;i++){ int u=-1,min=INF; for(int j=1;j<=n1;j++){ if(!flag[j]&&min>dis[j]){ u=j; min=dis[j]; } } if(u==-1) return ; flag[u]=1; for(int j=0;j<que[u].size();j++){ ac temp_3; temp_3=que[u][j]; if(!flag[j]&&dis[temp_3.v]<dis[u]+min){ dis[j]=dis[u]+min; } } } }
优化后的迪杰斯特拉+bfs
void dijkstra() { memset(dis,INF,sizeof(dis)); memset(flag,0,sizeof(flag)); dis[1]=0; priority_queue<ac>qu; ac temp_1; temp_1.v=1; temp_1.c=0; qu.push(temp_1); while(!qu.empty()){ ac temp_2=qu.top(); qu.pop(); int v=temp_2.v; if(dis[v]<temp_2.c||flag[v]) continue; if(v==n1) return ; flag[v]=1; for(int i=0;i<que[v].size();i++){ ac temp_3=que[v][i]; if(!flag[temp_3.v]&&dis[temp_3.v]>dis[v]+temp_3.c){ temp_3.c=dis[temp_3.v]=dis[v]+temp_3.c;//因为que是优先队列,所以如果要把temp_3入队,要把temp_3.c的值更新(挠头) 一开始没想到,在大佬的帮助下,才改正。。 qu.push(temp_3); } } } }
唉,就这样吧,如果各位大佬发现有错的地方可以在评论里指出来,以便小弟及时改正·······