题目描述 Description
幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
输入描述 Input Description
输入的第一行是两个整数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 Description
输出一行,表示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
样例输出 Sample Output
11
数据范围及提示 Data Size & Hint
对于30%的数据,保证 N<=100
对于100%的数据,保证 N<=100000
对于所有的数据,保证 K<=100000,1<=X<=5,1<=A, B<=N
差分约束系统:
1、a = b:建双向边,权值为0
2、a < b :b-a >= 1—>b>=a+1;建a到b 权值为1的边
3、a >= b : a >= b+0 建b到a权值为0的边
4、a > b:a-b >= 1—->a >= b+1;建b到a权值为1的边
5、a <= b:建a到b权值为0的边
跑一遍最长路
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN = 200000;
int head[MAXN],nxt[MAXN<<1],tim[MAXN],tot,n,m;
long long dis[MAXN];
bool vis[MAXN],flag = 0;
struct Edge
{
int from,to,cost;
}edge[MAXN<<1];
void build(int f,int t,int d)
{
edge[++tot].from = f;
edge[tot].to = t;
edge[tot].cost = d;
nxt[tot] = head[f];
head[f] = tot;
}
deque <int>q;
void spfa(int s)
{
memset(dis,-1,sizeof(dis));
dis[s] = 0;
vis[s] = 1;tim[0]=1;
q.push_front(s);
while(!q.empty())
{
int x = q.front();
q.pop_front();
vis[x] = 0;
for(int i = head[x]; i ; i = nxt[i])
{
Edge e = edge[i];
if(dis[e.to] < dis[x]+e.cost)
{
dis[e.to] = dis[x]+e.cost;
if(++tim[e.to] > n)
{
flag = 1;
return ;
}
if(!vis[e.to])
{
if(q.empty())
q.push_back(e.to );
else if(dis[q.front()] < dis[e.to])
q.push_front(e.to );
else
q.push_back(e.to);
vis[e.to] = 1;
}
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
int t,a,b;
for(int i = 1; i <= m; i ++)
{
scanf("%d%d%d",&t,&a,&b);
if(t == 1)build(a,b,0),build(b,a,0);
else if(t == 2)
{
build(a,b,1);
}
else if(t == 3)
build(b,a,0);
else if(t == 4)
build(b,a,1);
else if(t == 5)
build(a,b,0);
}
for(int i = n; i >= 1; i --)
build(0,i,1);
spfa(0);
if(flag)
puts("-1");
else
{
long long ans = 0;
for(int i = 1; i <= n; i ++)
ans += dis[i];
printf("%lld\n",ans);
}
return 0;
}