#差分约束,SPFA#洛谷 1993 小 K 的农场

题目


分析

对于描述1,也就是\((a,b,-c)\)\(b\)\(a\)至多多\(-c\)
对于描述2,也就是\((b,a,c)\)\(a\)\(b\)至多多\(c\)
对于描述3,也就是\((a,b,0),(b,a,0)\)
用SPFA判负环就可以了


代码

#include <cstdio>
#include <cctype>
#include <deque>
#include <cstring>
#define rr register
using namespace std;
const int N=5011; deque<int>q;
struct node{int y,w,next;}e[N*3];
int as[N],dis[N],cNt[N],v[N],n,k,m;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void add(int x,int y,int w){e[++k]=(node){y,w,as[x]},as[x]=k;}
signed main(){
	n=iut(),m=iut();
	memset(as,-1,sizeof(as));
	for (rr int i=1;i<=n;++i) add(0,i,0);
	for (rr int i=1;i<=m;++i){
		rr int op=iut(),x=iut(),y=iut();
		if (op==1) add(x,y,-iut());
		else if (op==2) add(y,x,iut());
		     else add(x,y,0),add(y,x,0);
	}
	memset(dis,0x3f,sizeof(dis));
	q.push_back(0),dis[0]=0,v[0]=1;
	while (q.size()){
		rr int x=q.front(); q.pop_front();
		for (rr int i=as[x];~i;i=e[i].next)
		if (dis[e[i].y]>dis[x]+e[i].w){
			dis[e[i].y]=dis[x]+e[i].w;
			if (++cNt[e[i].y]==n&&e[i].w<0) return !printf("No");
			if (!v[e[i].y]){
			    v[e[i].y]=1;
				if (q.size()&&dis[e[i].y]<dis[q.front()]) q.push_front(e[i].y);
				    else q.push_back(e[i].y);
			}
		}
		v[x]=0;
	}
	return !printf("Yes");
}
posted @ 2020-08-18 20:55  lemondinosaur  阅读(72)  评论(0编辑  收藏  举报