差分约束裸题,a==b的话分别建a>=b a<=b的边就行。倒序加边不然会TLE是什么鬼
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define ll long long
using namespace std;
const int maxn=500010,inf=1e9;
struct poi{int too,pre,sum;}e[maxn];
int n,m,x,y,z,front,rear,tot;
ll dist[maxn],ans;
int h[maxn],v[maxn],last[maxn],tim[maxn];
bool flag;
void read(int &k)
{
int f=1;k=0;char c=getchar();
while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
k*=f;
}
void add(int x,int y,int z){e[++tot].too=y;e[tot].sum=z;e[tot].pre=last[x];last[x]=tot;}
void spfa()
{
for(int i=0;i<=n;i++)dist[i]=-inf;
dist[0]=0;v[0]=1;front=rear=0;h[++rear]=0;
while(front!=rear)
{
int now=h[++front];if(front==maxn)front=-1;
for(int i=last[now],too=e[i].too;i;i=e[i].pre,too=e[i].too)
if(dist[too]<dist[now]+e[i].sum)
{
dist[too]=dist[now]+e[i].sum;
if(++tim[too]>2333){printf("-1");flag=1;return;}
if(!v[too])
{
v[too]=1;h[++rear]=too;
if(rear==maxn)rear=-1;
}
}
v[now]=0;
}
}
int main()
{
read(n);read(m);
for(int i=n;i;i--)add(0,i,1);
for(int i=1;i<=m;i++)
{
read(z);read(x);read(y);
if(z==1)add(x,y,0),add(y,x,0);
if(z==2)
{
if(x==y){printf("-1");return 0;}
add(x,y,1);
}
if(z==3)add(y,x,0);
if(z==4)
{
if(x==y){printf("-1");return 0;}
add(y,x,1);
}
if(z==5)add(x,y,0);
}
spfa();
if(flag)return 0;
for(int i=1;i<=n;i++)ans+=dist[i];
printf("%lld
",ans);
return 0;
}