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