博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P3275 [SCOI2011]糖果 && 差分约束(二)
阅读量:5221 次
发布时间:2019-06-14

本文共 2508 字,大约阅读时间需要 8 分钟。

学习完了差分约束是否有解, 现在我们学习求解最大解和最小解

首先我们回想一下是否有解的求解过程, 不难发现最后跑出来任意两点的最短路关系即为这两元素的最短路关系。
即: 最后的最短路蕴含了所有元素之间的约束关系

好的了解了这点, 我们可以想到, 既然我们知道了元素之间的约束关系, 确定了一个元素的值, 不就确定了全部元素的极值了吗?

求解时, 经常地把源点的值设为 一个特定的值 ,让源点变为基础点, 来拓展其他的点的值。这就是差分约束系统元素极值的大致求解思路了

还有一点需要注意, (哪里写的都是易证, 我也不会证明啊):

求取最小值时, 需要把差分约束一般式的小于等于号变为大于等于号, 跑最长路即为答案;

求取最大值时, 小于等于号不变, 求最短路即为答案;

P3275 [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\) ,当然也可以把源点到每个点的路径长度设为 \(1\)

Code

#include
#include
#include
#include
#include
typedef long long LL;using namespace std;LL RD(){ LL out = 0,flag = 1;char c = getchar(); while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();} while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();} return flag * out; }const LL maxn = 1000019,INF = 1e9 + 19;LL num, nr;LL head[maxn],nume = 1;struct Node{ LL v,dis,nxt; }E[maxn << 1];void add(LL u,LL v,LL dis){ E[++nume].nxt = head[u]; E[nume].v = v; E[nume].dis = dis; head[u] = nume; }LL d[maxn];bool inq[maxn];LL tim[maxn];bool SPFA(LL s){ for(LL i = 1;i <= num;i++)d[i] = -INF; queue
Q; d[s] = 0; Q.push(s); inq[s] = 1; while(!Q.empty()){ LL u = Q.front();Q.pop();inq[u] = 0; for(LL i = head[u];i;i = E[i].nxt){ LL v = E[i].v, dis = E[i].dis; if(d[u] + dis > d[v]){ d[v] = d[u] + dis; if(!inq[v]){ Q.push(v);inq[v] = 1; tim[v]++; if(tim[v] > num)return 0; } } } } return 1; }int main(){ num = RD();nr = RD(); for(LL i = num;i >= 1;i--)add(0, i, 1); for(LL i = 1;i <= nr;i++){ LL cmd = RD(), a = RD(), b = RD(); if(cmd == 1)add(a, b, 0), add(b, a, 0); else if(cmd == 2)add(a, b, 1); else if(cmd == 3)add(b, a, 0); else if(cmd == 4)add(b, a, 1); else add(a, b, 0); if(cmd % 2 == 0 && a == b){printf("-1\n");return 0;} } if(!SPFA(0)){printf("-1\n");return 0;} LL ans = 0; for(LL i = 1;i <= num;i++)ans += d[i]; printf("%lld\n", ans); return 0; }

转载于:https://www.cnblogs.com/Tony-Double-Sky/p/9347948.html

你可能感兴趣的文章
WPF移动Window窗体(鼠标点击左键移动窗体自定义行为)
查看>>
软件测试-----Graph Coverage作业
查看>>
django ORM创建数据库方法
查看>>
创建Oracle synonym 详解
查看>>
php7 新特性整理
查看>>
RabbitMQ、Redis、Memcache、SQLAlchemy
查看>>
linux查看端口占用
查看>>
hdu - 1226 超级密码 (bfs)
查看>>
Sql常见面试题 受用了
查看>>
知识不是来炫耀的,而是来分享的-----现在的人们却…似乎开始变味了…
查看>>
CSS背景颜色、背景图片、平铺、定位、固定
查看>>
口胡:[HNOI2011]数学作业
查看>>
我的第一个python web开发框架(29)——定制ORM(五)
查看>>
中国剩余定理
查看>>
基础笔记一
查看>>
uva 10137 The trip
查看>>
Count Numbers
查看>>
编写高质量代码改善C#程序的157个建议——建议110:用类来代替enum
查看>>
网卡bond技术
查看>>
UITabbarController的UITabbarItem(例:"我的")点击时,判断是否登录
查看>>