【SCOI2011 Day1】糖果
Time Limit:10000MS Memory Limit:165536K
Total Submit:273 Accepted:70
Case Time Limit:3000MS
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<cstdio>
#include<queue>
using namespace std;
#define maxn 100009
#define maxk 100009
#define inf 10000000000LL
inline void _read(int& d)
{
char t=getchar();bool f=false;
while(t<'0'||t>'9') {if(t=='-') f=true; t=getchar();}
for(d=0;t<='9'&&t>='0';t=getchar()) d=d*10+t-'0';
if(f) d=-d;
}
inline void _out(int d)
{
int o[30],top=1;
if(d==0){putchar('0');return ;}
if(d<0) {putchar('-');d=-d;}
while(d)
{
o[top++]=d%10;
d/=10;
}
for(--top;top;--top) putchar('0'+o[top]);
}
queue<int>q;
int next[maxk*5], end[maxk*5], last[maxn], cnt[maxn];
long long len[maxk*5], ans=0, dis[maxn];
int n, k, m=1;
bool havefu=false, f[maxn], cut=false;
void addv(int x, int y, long long z)
{
end[m]=y;
len[m]=z;
next[m]=last[x];
last[x]=m;
m++;
}
void _init()
{
int i, j, x, a, b;
_read(n);
_read(k);
for(i=n; i>=1; i--)
{
addv(0, i, 0);
}
for(i=1; i<=k; i++)
{
_read(x);
_read(a);
_read(b);
switch(x)
{
case (1):
addv(a, b, 0);
addv(b, a, 0);
break;
case (2):
if(a==b)
{
cut=1;
return;
}
addv(a, b, 1);
break;
case (3):
addv(b, a, 0);
break;
case (4):
if(a==b)
{
cut=1;
return;
}
addv(b, a, 1);
break;
case (5):
addv(a, b, 0);
break;
}
}
}
void spfa(int start)
{
int i, x, e;
havefu=false;
for(i=0; i<=n; i++)
{
dis[i]=-inf;
cnt[i]=0;
}
q.push(start);
f[start]=true;
dis[start]=1;
cnt[start]=1;
while(!q.empty())
{
x=q.front();
q.pop();
f[x]=false;
i=last[x];
while(i)
{
e=end[i];
if(dis[x]+len[i]>dis[e])
{
dis[e]=dis[x]+len[i];
if(f[e]==false)
{
q.push(e);
f[e]=true;
cnt[e]++;
if(cnt[e]==n)
{
havefu=true;
return;
}
}
}
i=next[i];
}
}
for(i=1; i<=n; i++) ans+=dis[i];
}
void _solve()
{
if(cut)
{
printf("-1");
return;
}
spfa(0);
if(havefu)
{
_out(-1);
}
else
{
printf("%I64d", ans);
}
}
int main()
{
_init();
_solve();
return 0;
}