差分约束系统是用最短路的三角不等式来得到题目中给定的不等式的一组解,具体来说,最短路中的不等式为if (dis[v]>dis[u]+len[p]) dis[v]=dis[u]+len[p],假设题目中给定不等式A<=B+5,那么转换的不等式即为if (dis[A]>dis[B]+5) dis[A]=dis[B]+5,这样就把数学中的不等式转换成图上的路径关系。每一个不等式变量的解即为它对应点的dis值。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100005
#define maxq 1000000
int pre[2*maxn],other[2*maxn],last[maxn],len[2*maxn];
int dis[maxn],cnt[maxn],q[maxn*10+5];
int n,m,l;
bool vis[maxn];
long long ans;
void connect(int x,int y,int z)
{
l++;
pre[l]=last[x];
last[x]=l;
other[l]=y;
len[l]=z;
}
void spfa(void)
{
int h=0,t=n;
while (h!=t)
{
h=h%maxq+1;
int u=q[h];vis[u]=0;
if (cnt[u]>n)
{
printf("-1\n");
return;
}
for (int p=last[u];p;p=pre[p])
{
int v=other[p];
if (dis[v]<dis[u]+len[p])
{
dis[v]=dis[u]+len[p];
if (!vis[v])
{
vis[v]=1;
cnt[v]++;
int temp=dis[q[h%maxq+1]];
if (dis[v]>temp)
{
q[h]=v;
h--;
if (h==0) h=maxq;
}
else
{
t=t%maxq+1;
q[t]=v;
}
}
}
}
}
for (int i=1;i<=n;i++) ans+=dis[i];
printf("%lld\n",ans);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int x,a,b;
scanf("%d%d%d",&x,&a,&b);
if (x==1)
{
connect(a,b,0);
connect(b,a,0);
}
if (x==2) connect(a,b,1);
if (x==3) connect(b,a,0);
if (x==4) connect(b,a,1);
if (x==5) connect(a,b,0);
}
for (int i=n;i>=1;i--)
{
q[i]=i;
vis[i]=1;
cnt[i]++;
dis[i]=1;
}
spfa();
return 0;
}