Description
幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
Input
输入的第一行是两个整数N,K。
接下来K行,表示这些点需要满足的关系,每行3个数字,X,A,B。
如果X=1, 表示第A个小朋友分到的糖果必须和第B个小朋友分到的糖果一样多;
如果X=2, 表示第A个小朋友分到的糖果必须少于第B个小朋友分到的糖果;
如果X=3, 表示第A个小朋友分到的糖果必须不少于第B个小朋友分到的糖果;
如果X=4, 表示第A个小朋友分到的糖果必须多于第B个小朋友分到的糖果;
如果X=5, 表示第A个小朋友分到的糖果必须不多于第B个小朋友分到的糖果;
Output
输出一行,表示lxhgww老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出-1。
Sample Input
5 7
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1
Sample Output
11
HINT
【数据范围】
对于30%的数据,保证 N<=100
对于100%的数据,保证 N<=100000
对于所有的数据,保证 K<=100000,1<=X<=5,1<=A, B<=N
题解
查分约束系统经典题。有一个坑爹的点,形成的是十万个点的一条链,如果从0到所有点顺序加边就会T,改成倒序就A了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define inf 1<<30
#define ll long long
using namespace std;
int n,m,tag,head[100002],zz;
struct bian{int to,nx,v;} e[500002];
int q[100002],dis[100002],pd[100002],ct[100002];
ll ans;
void insert(int x,int y,int z)
{
zz++; e[zz].to=y; e[zz].v=z; e[zz].nx=head[x]; head[x]=zz;
}
void init()
{
scanf("%d%d",&n,&m);
int i,x,y,z;
for(i=1;i<=m;i++)
{scanf("%d%d%d",&x,&y,&z);
if(x==1) {insert(y,z,0); insert(z,y,0);}
else if(x==2)
{if(y==z) {printf("-1\n"); tag=1; return;}
insert(y,z,1);
}
else if(x==3) insert(z,y,0);
else if(x==4)
{if(y==z) {printf("-1\n"); tag=1; return;}
insert(z,y,1);
}
else insert(y,z,0);
}
for(i=n;i>0;i--) insert(0,i,1);
}
bool spfa()
{
int i,t=0,w=1,p,x;
//for(i=0;i<=n;i++) dis[i]=-inf;
dis[0]=0; pd[0]=1; q[0]=0; ct[0]=1;
while(t!=w)
{x=q[t];
t=(t+1)%100002;
for(i=head[x];i;i=e[i].nx)
{p=e[i].to;
if(dis[x]+e[i].v>dis[p])
{dis[p]=dis[x]+e[i].v;
ct[p]++;
if(ct[p]>=n) return false;
if(!pd[p])
{q[w]=p; pd[p]=1; w=(w+1)%100002;}
}
}
pd[x]=0;
}
return true;
}
int main()
{
init();
if(tag==1) return 0;
if(!spfa()) {printf("-1\n"); return 0;}
int i;
for(i=1;i<=n;i++) ans+=dis[i];
printf("%lld\n",ans);
return 0;
}