题目大意:给定n个点和之间的大小关系,求每个点最少是多少(必须大于0)
差分约束系统,按照题目说的连边即可,记住少于和不少于的大小关系是不一样的
边集要开3倍 此外注意的是0到i的连边要从后往前连 不然TLE 坑B数据逗死我了
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 100100
using namespace std;
struct abcd{
int to,f,next;
}table[M*3];
int head[M],tot;
int n,m;
long long ans;
int f[M],times[M];
bool v[M];
void SPFA()
{
int i;
static queue<int> q;
memset(f,0xef,sizeof f);
q.push(0);f[0]=0;
while( q.size() )
{
int x=q.front();q.pop();
v[x]=0;
for(i=head[x];i;i=table[i].next)
if(f[table[i].to]<f[x]+table[i].f)
{
f[table[i].to]=f[x]+table[i].f;
times[table[i].to]=times[x]+1;
if(times[table[i].to]>n+1)
{
puts("-1");
exit(0);
}
if(!v[table[i].to])
v[table[i].to]=1,q.push(table[i].to);
}
}
}
void Add(int x,int y,int z)
{
table[++tot].to=y;
table[tot].f=z;
table[tot].next=head[x];
head[x]=tot;
}
int main()
{
int i,p,x,y;
cin>>n>>m;
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&p,&x,&y);
switch(p)
{
case 1:
Add(x,y,0);
Add(y,x,0);
break;
case 4:
swap(x,y);
case 2:
Add(x,y,1);
break;
case 3:
swap(x,y);
case 5:
Add(x,y,0);
break;
}
}
for(i=n;i;i--)
Add(0,i,1);
SPFA();
for(i=1;i<=n;i++)
ans+=f[i];
cout<<ans<<endl;
}