
据说这个题卡常?有什么关系,反正我用差分约束(
这个题可以明显看出是个差分约束板子(如果你想用差分约束做的话),我们直接把他给出的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;
}
在此附上板子题传送门:传送门
好了做完了……