1382:最短路(Spfa)

【解题思路】
该题顶点数量为100000,存储结构只能用邻接表。
边数 5*10^5相比于V  = 10 ^10 是很小的,可以认为题目中给定的图都是稀疏图,k会比较小,可以使用SPFA算法。
【注意】:题目中说可能有重边和自环,这两点并不会影响SPFA算法的运行,有重边就添加到邻接表中即可,不用特意排除重边。

【参考代码】

#include <bits/stdc++.h>
using namespace std;
const int N=100005;
const int oo=2139062143;
int num,nex[10*N],to[10*N],w[10*N],head[N];
bool sign[N];//标记
int dis[N];//距离
int n,m;
void add(int a,int b,int c){//邻接表存储
	nex[num]=head[a];// 将当前边链表的下一个节点指针(nex[num])设置为节点a的头节点(head[a])
	to[num]=b;// 设置这条边的终点为b,即从节点a指向节点b
	w[num]=c; // 设置这条边的权重(权值或成本)为c
	head[a]=num++;// 更新节点a的头节点为当前边的位置(num),然后num加1以便为下一条边预留位置
}
void Spfa(int g){
	memset(dis,0x7f,sizeof(dis));
	memset(sign,false,sizeof(sign));
	queue<int> q;
	dis[g]=0;
	q.push(g);
	sign[g]=true;
	while(!q.empty()){
		int x=q.front();
		q.pop();
		sign[x]=false;
		for(int i=head[x];i!=-1;i=nex[i]){
			int y=to[i],z=w[i];
			if(dis[y]>dis[x]+z){
				dis[y]=dis[x]+z;
				if(!sign[y]){
					sign[y]=true;
					q.push(y);
				}
			}
		}
	}
}
int main()
{
	cin>>n>>m;
	num=0;
	int a,b,c;
	for(int i=1;i<=n;i++) head[i]=-1;
	for(int i=1;i<=m;i++){
		cin>>a>>b>>c;
		add(a,b,c);add(b,a,c);
	}
	Spfa(1);
	cout<<dis[n];
	return 0;
}

【参考代码2】

#include<bits/stdc++.h>
using namespace std;
#define N 100005
struct Edge
{
	int t, w; 
	Edge(){}
	Edge(int a, int b):t(a),w(b){}
};
vector<Edge> edge[N];
bool vis[N];//vis[i]:顶点i是否在队列中 
int n, m, dis[N];//dis[i]:当前情况下v0到i的最短路径距离
void initGraph()
{
	int f, t, w;
    cin >> n >> m;
    for(int i = 1; i <= m; ++i)
    {
    	cin >> f >> t >> w;//从f到t权值w 
    	edge[f].push_back(Edge(t, w));
    	edge[t].push_back(Edge(f, w));
	}
}
void spfa(int sv)//sv起始点 
{
	memset(dis, 0x3f, sizeof(dis));//dis初始值为INF
	queue<int> que;
	dis[sv] = 0; 
	vis[sv] = true;
    que.push(sv);
	while(que.empty() == false)
    {
        int u = que.front();
        que.pop();
        vis[u] = false;
        for(int i = 0; i < edge[u].size(); ++i)
        {
            int v = edge[u][i].t, w = edge[u][i].w;
            if(dis[v] > dis[u] + w)
            { 
                dis[v] = dis[u] + w;
                if(vis[v] == false)
                {
                    vis[v] = true;
                    que.push(v);
                }
            }
        }
    }
}
int main()
{
	initGraph();
	spfa(1);
	cout << dis[n];
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值