糖果
题目描述
有n个小朋友,共有k个要求,求满足要求的最少的糖果数。
思路
显然的差分约束题,对于每个条件分别建边即可(假设第i个小朋友分到的糖果数为x[i]):
①x=1时,令x[a]≥x[b],x[b]≥x[a],即满足x[a]=x[b]。
②x=2时,x[a]<x[b],由于糖果数必定是整数,因此x[a]≤x[b]-1。
③x=3时,x[a]≥x[b]。
④x=4时,同理,x[a]≥x[b]+1。
⑤x=5时,x[a]≤x[b]。
按此约束条件建出图后在图上跑spfa即可,注意判断是否存在负环。
代码
#include <bits/stdc++.h> using namespace std; const int N=1e5+10,M=2e5+10; int nxt[M],to[M],w[M],head[N],tot; int dis[N],in[N],n,maxe; bool exist[N]; void add_edge(int x,int y,int v) { nxt[++tot]=head[x]; head[x]=tot; to[tot]=y; w[tot]=v; } void end() { printf("-1"); exit(0); } void spfa() { queue<int>q; for(int i=1;i<=n;i++) q.push(i),exist[i]=1,dis[i]=1,in[i]=1; while(!q.empty()) { int u=q.front();q.pop(); exist[u]=0; for(int i=head[u];i;i=nxt[i]) { int v=to[i]; if(dis[v]<dis[u]+w[i]) { dis[v]=dis[u]+w[i]; in[v]++; if(in[v]>=n)end(); if(!exist[v]) { exist[v]=1; q.push(v); } } } } } int main() { int k; scanf("%d%d",&n,&k); for(int i=1;i<=k;i++) { int x,a,b; scanf("%d%d%d",&x,&a,&b); if(x==1)add_edge(a,b,0),add_edge(b,a,0); else if(x==2)add_edge(a,b,1); else if(x==3)add_edge(b,a,0); else if(x==4)add_edge(b,a,1); else add_edge(a,b,0); if((x==2||x==4)&&a==b)end(); } spfa(); long long ans=0; for(int i=1;i<=n;i++) ans+=dis[i]; printf("%lld",ans); }