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
Sample Output
11
HINT
【数据范围】
对于30%的数据,保证 N<=100
对于100%的数据,保证 N<=100000
对于所有的数据,保证 K<=100000,1<=X<=5,1<=A, B<=N
差分约束!!同时跑最长路!!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int n, k, x, a, b;
const int maxx = 1000000;
int d[maxx], first[maxx], next[maxx], tot, len[maxx];
bool used[maxx], flag;
queue <int> q;
struct edge
{
int from, to, cost;
}es[maxx];
void init()
{
memset(d, -1, sizeof(d));
memset(first, -1, sizeof(first));
tot = 0;
}
void build(int ff, int tt, int dd)
{
es[++tot] = (edge){ff, tt, dd};
next[tot] = first[ff];
first[ff] = tot;
}
void spfa(int s)
{
d[s] = 0;
q.push(s);
used[s] = 1;
while(!q.empty())
{
int u = q.front();
q.pop();
used[u] = 0;
for(int i = first[u];i != -1;i = next[i])
{
int v = es[i].to;
if(d[v] < d[u] + es[i].cost)
{
d[v] = d[u] + es[i].cost;
len[v] = len[u] + 1;
if(len[v] > n + 1)
{
flag = 1;
return ;
}
if(!used[v])
{
q.push(v);
used[v] = 1;
}
}
}
}
}
int main()
{
init();
cin>>n>>k;
for(int i = 1;i <= k;i ++)
{
scanf("%d%d%d", &x, &a, &b);
if(x == 1)
{
build(a, b, 0);
build(b, a, 0);
}
else if(x == 2)
build(a, b, 1);
else if(x == 3)
build(b, a, 0);
else if(x == 4)
build(b, a, 1);
else if(x == 5)
build(a, b, 0);
}
for(int i = n;i >= 1;i --)
build(0, i, 0);
spfa(0);
if(flag)
{
cout<<-1<<endl;
return 0;
}
long long ans = 0;
for(int i = 1;i <= n;i ++)
{
ans+=d[i];
}
cout<<ans + n;
return 0;
}