NC20284 [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 7 1 1 2 2 3 2 4 4 1 3 4 5 5 4 5 2 3 5 4 5 1
输出
11
备注
对于30%的数据,保证
对于100%的数据,保证
对于所有的数据,保证
题解
知识点:差分约束。
这是一道差分约束模板题。
求最小值用最长路。关于建边利用不等式: 权为 ,则 。
如果存在正环,则无解。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 100007, K = 100007; template<class T> struct Graph { struct edge { int v, nxt; T w; }; int idx; vector<int> h; vector<edge> e; Graph(int n, int m) :idx(0), h(n + 1), e(m + 1) {} void add(int u, int v, T w) { e[++idx] = edge{ v,h[u],w }; h[u] = idx; } }; Graph <int> g(N, 3 * K);///一号坑,超级源点连边多了N个,原本边可能全是等于有2K个 int n, k; bool vis[N]; int dis[N], cnt[N]; stack<int> q;///二号坑,queue会被卡入点顺序 bool SPFA(int s) { memset(dis, -1, sizeof(dis)); q.push(s); dis[s] = 0; vis[s] = 1; while (!q.empty()) { int u = q.top(); q.pop(); vis[u] = 0; for (int i = g.h[u];i;i = g.e[i].nxt) { int v = g.e[i].v; int w = g.e[i].w; if (dis[v] < dis[u] + w) { dis[v] = dis[u] + w; cnt[v] = cnt[u] + 1; if (cnt[v] >= n + 1) return false;///三号坑,多了个超级源点,所以n+1 if (!vis[v]) { q.push(v); vis[v] = 1; } } } } return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); cin >> n >> k; for (int i = 1;i <= k;i++) { int x, a, b; cin >> x >> a >> b; if (x == 1) { g.add(a, b, 0); g.add(b, a, 0); } else if (x == 2) { g.add(a, b, 1); } else if (x == 3) { g.add(b, a, 0); } else if (x == 4) { g.add(b, a, 1); } else if (x == 5) { g.add(a, b, 0); } } for (int i = 1;i <= n;i++) g.add(n + 1, i, 1);///超级源点,为了方便,距离为0,到其他点为1,表示其他点>=0+1 /// 正边最长路用SPFA,A->B == dis[A] + w <= dis[B] if (!SPFA(n + 1)) cout << -1 << '\n'; else { ll ans = 0;///四号坑,最大值n^2/2 for (int i = 1;i <= n;i++) ans += dis[i]; cout << ans << '\n'; } return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/17028735.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧