The Shortest Path in Nya Graph

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.
 

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.
 

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.
 

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);
			}
		}
	}
}

唉,就这样吧,如果各位大佬发现有错的地方可以在评论里指出来,以便小弟及时改正·······

猜你喜欢

转载自blog.csdn.net/henu_jizhideqingwa/article/details/79916728