[SCOI2011]糖果
題目描述
幼兒園裏有N個小朋友,lxhgww老師現在想要給這些小朋友們分配糖果,要求每個小朋友都要分到糖果。但是小朋友們也有嫉妒心,總是會提出一些要求,比如小明不希望小紅分到的糖果比他的多,於是在分配糖果的時候,lxhgww需要滿足小朋友們的K個要求。幼兒園的糖果總是有限的,lxhgww想知道他至少需要準備多少個糖果,才能使得每個小朋友都能夠分到糖果,並且滿足小朋友們所有的要求。
輸入輸出格式
輸入格式:
輸入的第一行是兩個整數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個小朋友分到的糖果;
輸出格式:
輸出一行,表示lxhgww老師至少需要準備的糖果數,如果不能滿足小朋友們的所有要求,就輸出-1。
輸入輸出樣例
輸入樣例#1:
5 71 1 22 3 24 4 13 4 55 4 52 3 54 5 1
輸出樣例#1:
11
說明
【數據範圍】
對於30%的數據,保證 N<=100
對於100%的數據,保證 N<=100000
對於所有的數據,保證 K<=100000,1<=X<=5,1<=A, B<=N
題解:
差分約束題目,1操作看出a-b>=0 &&b-a>=0,所以a和b互相連一條權值爲0的邊。
2操作看成b-a>=1從a向b連一條長度爲1的邊,3看成a-b>=1,4看成a-b>=1,5看成b-a>=0求最長路。
代碼:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const LL max_n = 100001;
const LL inf = 1e9+7;
LL point[max_n],nxt[max_n<<1],v[max_n<<1],w[max_n<<1];
LL dis[max_n];
bool vis[max_n];
queue<LL> q;
LL n,k,x,y,c,tot,ans;
inline void init()
{
memset(point,-1,sizeof(point));
memset(nxt,-1,sizeof(nxt));
tot=-1;
}
inline void addedge(LL x,LL y,LL val)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; w[tot]=val;
}
inline bool spfa()
{
while(!q.empty())
{
LL now=q.front(); q.pop();
if(dis[now]>n) return true;
for(LL i=point[now]; i!=-1; i=nxt[i])
if(dis[now]+w[i]>dis[v[i]])
{
dis[v[i]]=dis[now]+w[i];
if(!vis[v[i]]) q.push(v[i]);
vis[v[i]]=true;
}
vis[now]=false;
}
return false;
}
int main()
{
scanf("%lld%lld",&n,&k);
init();
for(LL i=1; i<=k; ++i)
{
scanf("%lld%lld%lld",&c,&x,&y);
if(c==1) addedge(x,y,0),addedge(y,x,0);
else if(c==2) addedge(x,y,1);
else if(c==3) addedge(y,x,0);
else if(c==4) addedge(y,x,1);
else addedge(x,y,0);
if((c==2 || c==4) && x==y)
{
printf("-1\n");
return 0;
}
}
for(LL i=1; i<=n; ++i)
{
q.push(i);
dis[i]=1;
vis[i]=true;
}
if(spfa())
{
printf("-1\n");
return 0;
}
for(LL i=1; i<=n; ++i)
ans+=dis[i];
printf("%lld\n",ans);
return 0;
}