luogu P2294 [HNOI2005]狡猾的商人

背景:

终于又在高中部吃了一顿(差别好大)。

题目传送门:

https://www.luogu.org/problemnew/show/P2294

题意:

满足几个月的收支情况,求是否存在解。

思路:

前缀的差分约束(一样的)。
此时超级原点便不能为 0 0 0 30 m i n 30min 30min被坑走了),因为 1 − 1 = 0 1-1=0 11=0,一月份用到了 0 0 0这个点。

代码:

#include
#include
#include
#include
#include
using namespace std;
queue<int> f;
	struct node{int x,y,z,next;} a[800010];
	int last[400010],tot[400010],dis[400010];
	bool bz[400010];
	int n,m,st,len;
void ins(int x,int y,int z)
{
	a[++len]=(node){x,y,z,last[x]}; last[x]=len;
}
bool spfa()
{
	while(!f.empty()) f.pop();
	memset(tot,0,sizeof(tot));
	tot[st]=1;
	memset(dis,63,sizeof(dis));
	dis[st]=0;
	memset(bz,true,sizeof(bz));
	bz[st]=false;
	f.push(st);
	while(!f.empty())
	{
		int x=f.front();
		f.pop();
		for(int i=last[x];i!=-1;i=a[i].next)
		{
			int y=a[i].y;
			if(dis[x]+a[i].z<dis[y])
			{
				dis[y]=dis[x]+a[i].z;
				if(bz[y])
				{
					if(++tot[y]>=n) return false;
					f.push(y),bz[y]=false;
				}
			}
		}
		bz[x]=true;
	}
	return true;
}
void clear()
{
	len=0;
	st=n+1;
	memset(last,-1,sizeof(last));
}
int main()
{
	int T,x,y,z;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d %d",&n,&m);
		clear();
		for(int i=1;i<=n;i++)
			ins(st,i,0);
		for(int i=1;i<=m;i++)
		{
			scanf("%d %d %d",&x,&y,&z);
			ins(x-1,y,z),ins(y,x-1,-z);
		}
		printf(spfa()?"true\n":"false\n");
	}
}

你可能感兴趣的:(#,差分约束,#,spfa,差分约束,spfa)