题目链接
幼儿园里有 N 个小朋友,老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。
但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候, 老师需要满足小朋友们的 K 个要求。
幼儿园的糖果总是有限的,老师想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
输入格式
输入的第一行是两个整数 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 个小朋友分到的糖果。
小朋友编号从 1 到 N。
输出格式
输出一行,表示老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出 −1。
数据范围
1≤N<105,
1≤K≤105,
1≤X≤5,
1≤A,B≤N,
输入数据完全随机。
输入样例:
输出样例:
解题思路
差分约束
差分约束用来解决类似多个 xi≤xi+1+ci 这样的不等式的可行解或最优解的问题,而 xi≤xi+1+ci 正好对应求解最终最短路的形式,即求解最短路时,最终会有 xi≤c1+c2⋯+ck 的形式,即在所有的下界中取最小值,此时取得的 xi 为最大值,否则如果出现负环的话,即最终会循环到某个点,会产生矛盾,此时无解,同理,求解最长路对应求解每个 xi 的最小值,当出现正环时无解。另外,由于给出的关系可能都为相对关系,而求解的往往需要绝对关系,可以建立一个虚拟源点 x0,即 d[x0]=0,将该点添加到其他关系中连边
本题求解最小值,故求最长路,且要求所有 xi≥1,即 xi≥x0+1,将 0 到 1 之间连一条边权为 1 的边即可,其他建边同理,最后求一遍 spfa 即可
代码
#include <bits/stdc++.h>
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=1e5+5;
int n,k,x;
int d[N],cnt[N];
int h[N],e[N*3],w[N*3],ne[N*3],idx;
bool v[N];
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
bool spfa()
{
stack<int> stk;
stk.push(0);
v[0]=true;
memset(d,-0x3f,sizeof d);
d[0]=0;
while(stk.size())
{
int x=stk.top();
stk.pop();
v[x]=false;
for(int i=h[x];~i;i=ne[i])
{
int y=e[i],ww=w[i];
if(d[y]<d[x]+ww)
{
d[y]=d[x]+ww;
cnt[y]=cnt[x]+1;
if(cnt[y]>=n+1)return false;
if(!v[y])stk.push(y),v[y]=true;
}
}
}
return true;
}
int main()
{
scanf("%d%d",&n,&k);
memset(h,-1,sizeof h);
while(k--)
{
int a,b;
scanf("%d%d%d",&x,&a,&b);
if(x==1)add(a,b,0),add(b,a,0);
else if(x==2)add(a,b,1);
else if(x==3)add(b,a,0);
else if(x==4)add(b,a,1);
else
add(a,b,0);
}
for(int i=1;i<=n;i++)add(0,i,1);
if(!spfa())puts("-1");
else
{
LL res=0;
for(int i=1;i<=n;i++)res+=d[i];
printf("%lld",res);
}
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!