迪杰斯特拉 patA1003Emergency总结

#include<bits/stdc++.h>
using namespace std;
//由于点少,直接用矩阵存边。储存图需要一个矩阵(二维数组),边数edge,点数n,
//输入前需要初始化矩阵,故要有maxv和inf。迪杰斯特拉本身带有d[]最短距离,vis[]标记数组,由于需要最短路径条数,故需要num[]记录,以及第二尺度,用weight储存信息,用w记录最大队伍数
#define MAXV 510
#define INF 10000000
int n,edge,x,y;
int d[MAXV],G[MAXV][MAXV],weight[MAXV],w[MAXV],num[MAXV];//d,num,w只在djstrea里改 
bool vis[MAXV]={false};
void Djstra(int s)
{
	fill(d,d+MAXV,INF);
	memset(num,0,sizeof(num));
	memset(w,0,sizeof(w));//d,num,w,只在djstla算法里维护,故在这里初始化
	d[s]=0;
	w[s]=weight[s];
	num[s]=1;//这里需要注意,因为迪杰斯特拉是相当于递归算法,每次拿一个点最终算出整个图的最短路径,所以num,w,d都得有个头,即出发城市的
	//但是注意不能在这里把vis[s]变成已访问,需要在下面for里找s(并且是第一个)因为
	//下面维护num和w的方法跟s不一样,所以需要在这初始nums和ws
	//而下面还需要把新加入点出发的路径看一遍,要么把找其路径的方法在这里再写一遍,要么就在下面再把s纳入,显然后者更合适一点
	for(int i=0;i<n;i++)
	{
		int u=-1,MIN=INF;
		for(int j=0;j<n;j++)
		{
			if(vis[j]==false && d[j]<MIN)
			{
				u=j;MIN=d[j];
			}
		}
		if(u==-1)return;//别忘记当图不连通的时候
		vis[u]=true;//vis目的就是找到每次从点集里拿到s中那个点 即u 
		for(int k=0;k<n;k++)//同时维护d,num,和w
		{
			if(vis[k]==false && G[u][k]!=INF)
			{
				if(d[u]+G[u][k]<d[k])
				{
					d[k]=d[u]+G[u][k];
					num[k]=num[u];
					w[k]=w[u]+weight[k];
				}
				else if(d[u]+G[u][k]==d[k])
				{
					if(w[k]<w[u]+weight[k])
					{
					w[k]=w[u]+weight[k];}
					num[k]+=num[u];
				}
			}
		}
		
	}
 } 
int main()
{
	fill(G[0],G[0]+MAXV*MAXV,INF);
	scanf("%d %d %d %d",&n,&edge,&x,&y);
	for(int i=0;i<n;i++)
	scanf("%d",&weight[i]);
	for(int i=0;i<edge;i++)
	{
		int temx,temy,tem;
		scanf("%d %d %d",&temx,&temy,&tem);
		G[temx][temy]=tem;
		G[temy][temx]=tem;
	}
	Djstra(x);
	printf("%d %d\n",num[y],w[y]);
}

裸迪杰斯特拉算最短路径是只记录最短路径多长即最短距离,不考虑第二权值,不考虑最短路径怎么走。该题要求打印出最短路径条数及第二权值最大值(不要想着不要最短距离就不维护它。
具体见代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值