洛谷 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)的主要内容,如果未能解决你的问题,请参考以下文章