题目链接:https://www.luogu.org/problemnew/show/P1993
题解:
差分约束+判环。
值得注意的地方:
对于第 3 种情况,要建两条边(小心炸数组)。
最好还是用tarjan判环,然后在写spfa加上优化,这题数据范围比较小,作者没卡住。
如果范围再大点,或许又会有hack链接了
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e4+5,maxm=maxn*3;
int n,m,tot,lnk[maxn],son[maxm],nxt[maxm],w[maxm];
int q[maxn],til,hea,dis[maxn],vis[maxn];
int rad()
{
int ret=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
void add(int x,int y,int z){son[++tot]=y;nxt[tot]=lnk[x];w[lnk[x]=tot]=z;}
void spfa(int x)
{
vis[x]=1;
for (int i=lnk[x],y;i;i=nxt[i])
{
if (dis[y=son[i]]<=dis[x]+w[i]) continue;
if (vis[y]) {puts("No");exit(0);}
dis[y]=dis[x]+w[i];spfa(y);
}
vis[x]=0;
}
int main()
{
n=rad();m=rad();
for (int i=1,p,a,b,c;i<=m;++i)
{
p=rad();a=rad();b=rad();
if (p<3) c=rad();
switch(p)
{
case 1:add(a,b,-c);break;
case 2:add(b,a,c);break;
default:add(b,a,0);add(a,b,0);break;
}
}
memset(dis,63,sizeof dis);*dis=0;
for (int i=1;i<=n;++i) add(0,i,0);
spfa(0);
puts("Yes");
return 0;
}