天梯L2-001 紧急救援 (纯dij不太熟)

 PTA | 程序设计类实验辅助教学平台

有空优先队列试一下。 

#include<bits/stdc++.h>
using namespace std;
const int N=510;
const int inf=0x3f3f3f3f;
typedef long long ll;
int n,m,s,t,a[N],vis[N],num[N],dis[N],pre[N],road[N],g[N][N];
//N<1000用矩阵可以过,以后优先用矩阵。前向星在这题会超时!搭配优先队列用吧 
void dfs(int v){
	if(v==s) return ;
	dfs(pre[v]);
	printf("%d ",pre[v]);
}
void dij(int s,int t){
	while(s!=t){//不能直接dis[v]==inf,因为要考虑多条路径 
		int minn=inf;
		for(int v=0;v<n;v++){
			if(!vis[v]&&g[s][v]!=inf){
				if(dis[v]>dis[s]+g[s][v]){
					dis[v]=dis[s]+g[s][v];
					num[v]=num[s]+a[v];
					road[v]=road[s];
					pre[v]=s;
				}
				else if(dis[v]==dis[s]+g[s][v]){
					if(num[v]<num[s]+a[v]){
						num[v]=num[s]+a[v];
						pre[v]=s;	
					}
					road[v]=road[v]+road[s];
					//+road[s],而不是1。v可以通过s过来是多了一类,但到s又有好几种方法 
				}
//				if(minn>dis[v]){
//					nex=v;minn=dis[v];
//				}因为下面逐个遍历了,所以这里可以省了 
			}
		}
		//这里不是找到最短路就行了,还要考虑等于的情况,所以不能直接赋nex,同一层的并列情况会漏所以要遍历一遍n个数。按层的话可以试一下优先队列写 
		for(int i=0;i<n;i++){
			if(!vis[i]&&minn>dis[i]){			
				s=i;minn=dis[i];
			}
		} 
		if(minn==inf) break;//找s的变了,剪枝得放后边了 
		vis[s]=1;
	}
}
int main(){
	int x,y,z;
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
		for(int j=0;j<n;j++) g[i][j]=inf;
		vis[i]=0;road[i]=0;
		num[i]=a[i];
		dis[i]=inf;pre[i]=-1;
	}
	for(int i=0;i<m;i++){
		scanf("%d%d%d",&x,&y,&z);
		g[x][y]=z;g[y][x]=z;
	}
	dis[s]=0;vis[s]=1;
	road[s]=1;//
	dij(s,t);
	cout<<road[t]<<" "<<num[t]<<endl;
	dfs(t);
	printf("%d\n",t);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_50904510/article/details/121895330