传送门
题目大意:n个点每一个点有一个权,有m个限制:1 a b c
d(a)-d(b)>=c; 2 a b c
d(a)-d(b)<=c;3 a b
d(a)=d(b),判断是否有可行解
对于三个限制移项啥的可以化出来一些不等式:d(b)<=d(a)-c;d(a)<=d(b)+c;d(b)<=d(a),d(a)<=d(b)
对于一个形如d(x)<=d(y)+z的等式,连边y->x,z构造出最短路模型
这道题没有源点,所以强行加一个源点0,然后因为要从源点连向每一个点,所以强行d(i)<=d(0)
设d(0)=0,虽然求出来的所有的d都是非正数,但是所有的d同时加上一个数都是可行解,所以没有影响;只需要看图中是否有负权环即可
用深搜版spfa判断负环快很多很多…
普通spfa
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 10005
#define E 50005
int n,m,ans;
int tot,point[N],nxt[E],v[E],c[E];
int dis[N],cnt[N];bool vis[N];
queue <int> q;
void add(int x,int y,int z)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;
}
int spfa()
{
memset(dis,127,sizeof(dis));
dis[0]=0;vis[0]=1;cnt[0]=1;q.push(0);
while (!q.empty())
{
int now=q.front();q.pop();
vis[now]=0;
for (int i=point[now];i;i=nxt[i])
if (dis[v[i]]>dis[now]+c[i])
{
dis[v[i]]=dis[now]+c[i];
if (!vis[v[i]])
{
++cnt[v[i]];
if (cnt[v[i]]>n) return 0;
vis[v[i]]=1;
q.push(v[i]);
}
}
}
return 1;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i)
{
int opt,a,b,c;scanf("%d",&opt);
if (opt==1)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,-c);
}
else if (opt==2)
{
scanf("%d%d%d",&a,&b,&c);
add(b,a,c);
}
else
{
scanf("%d%d",&a,&b);
add(a,b,0);add(b,a,0);
}
}
for (int i=1;i<=n;++i) add(0,i,0);
ans=spfa();
if (!ans) puts("No");
else puts("Yes");
}
深搜版spfa
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 10005
#define E 50005
int n,m;
int tot,point[N],nxt[E],v[E],c[E];
int dis[N];bool vis[N],flag;
queue <int> q;
void add(int x,int y,int z)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;
}
void spfa(int x)
{
vis[x]=1;
for (int i=point[x];i;i=nxt[i])
if (dis[v[i]]>dis[x]+c[i])
{
dis[v[i]]=dis[x]+c[i];
if (vis[v[i]])
{
flag=1;
return;
}
spfa(v[i]);
if (flag) return;
}
vis[x]=0;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i)
{
int opt,a,b,c;scanf("%d",&opt);
if (opt==1)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,-c);
}
else if (opt==2)
{
scanf("%d%d%d",&a,&b,&c);
add(b,a,c);
}
else
{
scanf("%d%d",&a,&b);
add(a,b,0);add(b,a,0);
}
}
for (int i=1;i<=n;++i) add(0,i,0);
memset(dis,127,sizeof(dis));dis[0]=0;
flag=0;spfa(0);
if (!flag) puts("Yes");
else puts("No");
}