洛谷 P5960 模板差分约束算法(spfa)

Posted 尹昱钦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P5960 模板差分约束算法(spfa)相关的知识,希望对你有一定的参考价值。

传送门


解题思路

给你\\(n\\)个不等式,\\(ai<=aj+k\\)
像极了最短路中松弛的式子
所以做法就出来了:
对于每一个是上面形式的式子,我们从\\(j\\)\\(i\\)连一条长度为\\(k\\)的边,这样我们保证了到\\(i\\)的最短路一定\\(<=\\)\\(j\\)的最短路。
建立一个超级源点,连向每一个点,边权为\\(0\\),求一遍最短路spfa,每个点到超级源点的最短路长度即为值的大小,而刚刚边权\\(0\\)其实就是确定了最终解的上界大小,即解都\\(<=0\\)
注意有负环则无解(用spfa可判断)。

AC代码

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=5005;
int n,m,p[maxn],dis[maxn],cnt,vis[maxn],times[maxn];
struct node{
	int v,next,w;
}e[maxn*2];
void insert(int u,int v,int w){
	cnt++;
	e[cnt].v=v;
	e[cnt].w=w;
	e[cnt].next=p[u];
	p[u]=cnt;
}
queue<int> q;
bool spfa(){
	memset(dis,0x3f,sizeof(dis));
	dis[0]=0;
	q.push(0);
	vis[0]=1;
	while(!q.empty()){
		int u=q.front();
		q.pop();
		vis[u]=0;
		times[u]++;
		if(times[u]>n) return false;
		for(int i=p[u];i!=-1;i=e[i].next){
			int v=e[i].v;
			if(dis[v]>dis[u]+e[i].w){
				dis[v]=dis[u]+e[i].w;
				if(!vis[v]){
					vis[v]=1;
					q.push(v);
				}
			}
		}
	}
	return true;
}
int main()
{
	memset(p,-1,sizeof(p));
    cin>>n>>m;
    for(int i=1;i<=m;i++){
    	int u,v,w;
    	scanf("%d%d%d",&v,&u,&w);
    	insert(u,v,w);
	}
	for(int i=1;i<=n;i++) insert(0,i,0);
	if(!spfa()){
		cout<<"NO"<<endl;
		return 0;
	}
	for(int i=1;i<=n;i++) cout<<dis[i]<<\' \';
    return 0;
}

以上是关于洛谷 P5960 模板差分约束算法(spfa)的主要内容,如果未能解决你的问题,请参考以下文章

[luoguP1993] 小 K 的农场(差分约束 + spfa 判断负环)

模板前向星 SPFA求最短(长)路

ZOJ 2770 差分约束+SPFA

HDOJ1534差分约束+SPFA

poj 1201 Intervals差分约束+spfa

2019.8.3刷题统计