差分约束
裸题,
a< b等价于a+1<=b,
这就类似松弛操作d[x]+w[i]<=d[y],转化为最长路问题。
#include<cstdio>
#include<cstring>
#define N 100005
using namespace std;
int in()
{
register int r = 0;
register char c = getchar();
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9')r=r*10+c-'0',c=getchar();
return r;
}
struct edge{int next,to,val;}e[N*2];
int ecnt=0, last[N], q[N], vis[N], n, k;
long long d[N];
bool inq[N];
void add(int a, int b, int c)
{
e[++ecnt]=(edge){last[a],b,c};
last[a]=ecnt;
}
bool SPFA()
{
int head=0, tail=0;
for(int i = 1; i <= n; i++)
{
q[tail++]=i;
d[i]=1;
}
for(;head!=tail;head++)
{
int x=q[head];
inq[x]=0;
if(head==N)head=0;
for(int i = last[x]; i; i=e[i].next)
{
int y=e[i].to;
if(d[x]+e[i].val>d[y])
{
vis[y]++;
if(vis[y]>=n)return false;
d[y]=d[x]+e[i].val;
if(inq[y]==0)
{
inq[y]=1;
q[tail++]=y;
if(tail==N)tail=0;
}
}
}
}
return true;
}
int main()
{
// freopen("data.in","r",stdin);
n=in(), k=in();
for(int x, a, b, i = 1; i <= k; i++)
{
x=in(); a=in(); b=in();
switch(x)
{
case 1: add(a,b,0); add(b,a,0); break;
case 2: if(a==b)return !printf("-1\n"); add(a,b,1); break;
case 3: add(b,a,0); break;
case 4: if(a==b)return !printf("-1\n"); add(b,a,1); break;
case 5: add(a,b,0); break;
}
}
if(!SPFA())printf("%d\n",-1);
else
{
long long ans=0;
for(int j = 1; j <= n; j++)
ans+=d[j];
printf("%lld\n",ans);
}
}