SPFA算法模板

struct node{
	int v,w;//终点和权重 
};
vector<node>adj[maxn];
int vis[maxn];
int d[maxn];
const int Inf=0x3f3f3f3f;
queue<int>q;
int n,m,s,t;
void spfa(){
	for(int i=1;i<=n;i++){
		d[i]=Inf;
	}
	d[s]=0;
	vis[s]=1;
	q.push(s);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=0;i<adj[u].size();i++){
			int v=adj[u][i].v;
			int w=adj[u][i].w;		
			if(d[v]>d[u]+w){
				d[v]=d[u]+w;
				if(!vis[v]){//点如果已经访问过(已经在队列里)就不要再入队。 
					vis[v]=1;
					q.push(v);
				}
			}
		}
	}
	
}

洛谷3371

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define inf 2147483647
using namespace std;
struct edge{
    int v,w;
    edge(int a,int b){
    	v=a;
    	w=b;
	}
};
int n,m,st;
int dis[10005];
bool inq[10005];
vector<edge>adj[10005];
void SPFA(){
    for(int i=1;i<=n;i++){
        dis[i]=inf;
    }
    dis[st]=0;
    queue<int>q;
   q.push(st);
    inq[st]=1;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        inq[u]=0;
        for(int i=0;i<adj[u].size();i++){
            int vv=adj[u][i].v;
            int ww=adj[u][i].w;
            if(dis[u]+ww<dis[vv]){
                dis[vv]=dis[u]+ww;
                if(!inq[vv]){
                    q.push(vv);
                    inq[vv]=1;
                }
            }
        }
    }
}
int main(){
    scanf("%d%d%d",&n,&m,&st);
    for(int i=1;i<=m;i++){
        int u,v,s;
        scanf("%d%d%d",&u,&v,&s);
        adj[u].push_back(edge(v,s));
    }
   SPFA();
    for(int i=1;i<=n;i++){
        printf("%d ",dis[i]);
    }
    return 0;
}

(不知道为什么莫名WA了很多次T-T Orz)
洛谷T50283
这道题和上一道题很像,不同的是求所有的点到给定点的距离。按之前的想法,我们得跑n次spfa,肯定会超时,我们考虑反向建图,转为求给定点到所有点的距离,那么只要一次spfa。

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
const int inf=0x3f3f3f3f;
using namespace std;
struct edge{
    int v,w;
    edge(int a,int b){
    	v=a;
    	w=b;
	}
};
int n,m,st;
int dis[5005];
bool inq[5005];
vector<edge>adj[5005];
void SPFA(){
    for(int i=1;i<=n;i++){
        dis[i]=inf;
    }
    dis[st]=0;
    queue<int>q;
   q.push(st);
    inq[st]=1;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        inq[u]=0;
        for(int i=0;i<adj[u].size();i++){
            int vv=adj[u][i].v;
            int ww=adj[u][i].w;
            if(dis[u]+ww<dis[vv]){
                dis[vv]=dis[u]+ww;
                if(!inq[vv]){
                    q.push(vv);
                    inq[vv]=1;
                }
            }
        }
    }
}
int main(){
    scanf("%d%d%d",&n,&m,&st);
    for(int i=1;i<=m;i++){
        int u,v,s;
        scanf("%d%d%d",&u,&v,&s);
        adj[v].push_back(edge(u,s));
    }
     SPFA();
    for(int i=1;i<=n;i++){
    	if(dis[i]==inf)printf("-1 ");
    	else 
        printf("%d ",dis[i]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值