hdu4725最短路变形 添加点
The Shortest Path in Nya Graph
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4872 Accepted Submission(s): 1122
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 <= 105) and C(1 <= C <= 103), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
The second line has N numbers li (1 <= li <= N), which is the layer of ith node belong to.
Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 104), 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 <= 105) and C(1 <= C <= 103), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
The second line has N numbers li (1 <= li <= N), which is the layer of ith node belong to.
Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 104), 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
题意: 有n个地点,m条边,每条边耗费w,每个点又属于一些集合,相邻的集合之间的点可以直接通行,耗费c。现在求1到n的最少费用。
思路:可以把集合当做一个点,从集合到集合内的点费用为0,点到相邻的集合费用为c,这样就既保证了不用暴力枚举相邻集合里面的每个点,有保证相邻集合里的点的最短路(表达能力不好 -。-#!)。
就是这张图的意思:
然后一遍dij+heap就好。
#include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<string> #include<time.h> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define INF 1000000001 #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int MAXN = 100010; struct node { int to; int val; int next; }edge[MAXN * 10]; int pre[MAXN*3],vis[MAXN*3],dis[MAXN*3],n,m,k,c,ind; int num[MAXN],ok[MAXN]; void add(int x,int y,int z) { edge[ind].to = y; edge[ind].val = z; edge[ind].next = pre[x]; pre[x] = ind ++; } struct Node { int p; ll val; Node(){} Node(int fp,int fval):p(fp),val(fval){} friend bool operator < (Node fa,Node fb){ return fa.val > fb.val; } }; void dij(int s) { priority_queue<Node>fq; for(int i = 1; i <= k; i++){ dis[i] = INF; vis[i] = 0; } dis[s] = 0; fq.push(Node(s,0)); while(!fq.empty()){ Node tp = fq.top(); fq.pop(); vis[tp.p] = 1; for(int i = pre[tp.p]; i != -1; i = edge[i].next){ int t = edge[i].to; if(!vis[t] && dis[t] > dis[tp.p] + edge[i].val){ dis[t] = dis[tp.p] + edge[i].val; fq.push(Node(t,dis[t])); } } } } int main() { int t,ff = 0; scanf("%d",&t); while(t--){ memset(num,0,sizeof(num)); memset(ok,0,sizeof(ok)); scanf("%d%d%d",&n,&m,&c); int x; ind = 0; memset(pre,-1,sizeof(pre)); for(int i = 1; i <= n; i++){ scanf("%d",&x); ok[x] = 1; num[i] = x; } for(int i = 1; i <= n; i++){//点与集合之间连边 add(n+num[i],i,0); if(num[i] > 1)add(i,n+num[i]-1,c); if(num[i] < n)add(i,n+num[i]+1,c); } int y,z; for(int i = 1; i <= m; i++){ scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } //cout<<k<<endl; k = 2 * n; dij(1); printf("Case #%d: ",++ff); if(dis[n] >= INF){ printf("-1\n"); } else { printf("%d\n",dis[n]); } } return 0; }