洛谷 P1993 小 K 的农场

据说这个题卡常?有什么关系,反正我用差分约束(

这个题可以明显看出是个差分约束板子(如果你想用差分约束做的话),我们直接把他给出的3个情况整理成3个条件:

1:a-b>=c

2:a-b<=c

3:a=b

看起来已经很明显了呢

我们跑最短路,再来转换一下……

1:b<=a+-c

2:a<=b+c

3:a=b

啊更明显了!所以我们直接建图,然后打一遍板子这题就过了

当你觉得你可以秒掉这个题的时候,生活会给你重重一击,并告诉你,“你代码有bug~看不出来的那种~”

emm写码5分钟调试两小时。

在这里我还要提醒一下很容易错的几点(应该只有我错了)

不要把路径的起点和终点搞反

不要把链式前向星的遍历写错

不要把两个不同类型的遍历来运算

好了真的结束了,这个题是裸裸的差分约束,真的除了建图和板子没区别……

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
long long n,m,a,b,c,s;
queue<long long>q;
struct hehe
{
	long long w,syg,cd;//结尾,上一个的编号,和到达结尾的长度 
}lsqxx[12005];
long long head[7005],ans;
void add(long long t,long long w,long long cd)//链式前向星存图 
{
	ans++;
	lsqxx[ans].w=w;
	lsqxx[ans].syg=head[t];
	lsqxx[ans].cd=cd;
	head[t]=ans;
}
long long wz,bj[7005],zx[7005],cs[7005];
bool hs()
{
	for(int i=1;i<=n;i++)//附一个极大值 
	{
		zx[i]=10000000;
	} 
	zx[0]=0;
	while(q.empty()!=true)
	{
		wz=q.front();
		q.pop();
		bj[wz]=0;
		for(int i=head[wz];i!=0;i=lsqxx[i].syg)//这似曾相识的代码,没见过的可以去看看我写的板子题,就在下面链接处 
		{
			if(zx[lsqxx[i].w]>zx[wz]+lsqxx[i].cd)
			{
				zx[lsqxx[i].w]=zx[wz]+lsqxx[i].cd;
				cs[lsqxx[i].w]++;
				if(cs[lsqxx[i].w]>=n)
				{
					return false;
				}
				if(bj[lsqxx[i].w]==0)
				{
					bj[lsqxx[i].w]=1;
					q.push(lsqxx[i].w);
				}
			}
		}
	}
	return true;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		add(0,i,0);//超级原点,维护图的联通就靠你了
	}
	for(int i=1;i<=m;i++)
	{
		cin>>s;
		if(s==1)
		{
			cin>>a>>b>>c;
			add(a,b,-c);//建图上面解释过了b<=a+-c 
		}else if(s==2)
		{
			cin>>a>>b>>c;
			add(b,a,c);//a<=b+c 
		}else if(s==3)
		{
			cin>>a>>b;
			add(a,b,0);//a=b
			add(b,a,0);//a=b
		}
	}
	q.push(0);//0是超级原点 
	if(hs()==false)//不可能的 
	{
		cout<<"No"<<endl;
	}else
	{
		cout<<"Yes"<<endl;
	}
	return 0;
}

在此附上板子题传送门:传送门

好了做完了……

猜你喜欢

转载自www.cnblogs.com/lichangjian/p/13399740.html