[SCOI 2011]糖果

Description

题库链接

给出 \(N\) 个节点,节点有正点权, \(K\) 个三元组 \((X,A,B)\) 来描述节点点权之间的关系。

  1. 如果 \(X=1\) , 表示 \(A\) 的点权必须和 \(B\) 的点权相等;
  2. 如果 \(X=2\) , 表示 \(A\) 的点权必须小于 \(B\) 的点权;
  3. 如果 \(X=3\) , 表示 \(A\) 的点权必须不小于 \(B\) 的点权;
  4. 如果 \(X=4\) , 表示 \(A\) 的点权必须大于 \(B\) 的点权;
  5. 如果 \(X=5\) , 表示 \(A\) 的点权必须不大于 \(B\) 的点权

问如何安排点权使点权和最小。

\(1\leq N,K\leq 100000\)

Solution

很显然是一个差分约束系统的模型。但值得注意的是由于题目是求最小值,所以构建的差分约束系统应该是建立在“最长路”的基础上的,所以不等号要用 \('\geq'\) 。

对于建图,我们记连一条有向边从 \(u\) 到 \(v\) 边权为 \(c\) 为 \((u,v,c)\) 。对于题中的五种情况:

  1. 如果 \(X=1\) , \((u,v,0), (v,u,0)\) ;
  2. 如果 \(X=2\) , \((u,v,1)\) ;
  3. 如果 \(X=3\) , \((v,u,0)\) ;
  4. 如果 \(X=4\) , \((v,u,1)\) ;
  5. 如果 \(X=5\) , \((u,v,0)\)

然后依旧是 \(dfs-SPFA\) 来做,但是好像卡 \(SPFA\) ,好像将超级源点建边顺序取反就好了...

Code

//It is made by Awson on 2018.2.4
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = 100000;
void read(int &x) {
    char ch; bool flag = 0;
    for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
    for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
    x *= 1-2*flag;
}
void print(LL x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(LL x) {if (x < 0) putchar('-'); print(Abs(x)); }

int n, k, x, u, v;
struct tt {int to, next, cost; }edge[(N<<2)+5];
int path[N+5], top, vis[N+5], dist[N+5];
void add(int u, int v, int c) {
    edge[++top].to = v, edge[top].cost = c, edge[top].next = path[u], path[u] = top;
} 

bool dfs(int u) {
    vis[u] = 1;
    for (int i = path[u]; i; i = edge[i].next)
        if (dist[edge[i].to] < dist[u]+edge[i].cost) {
            if (vis[edge[i].to] != 0) return true;
            dist[edge[i].to] = dist[u]+edge[i].cost;
            if (dfs(edge[i].to)) return true;
        }
    vis[u] = 0;
    return false;
}
void work() {
    read(n), read(k);
    for (int i = n; i >= 1; i--) add(0, i, 1);
    for (int i = 1; i <= k; i++) {
        read(x), read(u), read(v);
        if (x == 1) add(u, v, 0), add(v, u, 0);
        else if (x == 2) add(u, v, 1);
        else if (x == 3) add(v, u, 0);
        else if (x == 4) add(v, u, 1);
        else add(u, v, 0);
    }
    if (dfs(0)) {puts("-1"); return; }
    LL ans = 0;
    for (int i = 1; i <= n; i++) ans += dist[i];
    writeln(ans);
}
int main() {
    work(); return 0;
}

原文地址:https://www.cnblogs.com/NaVi-Awson/p/8414070.html

时间: 2024-11-13 09:33:11

[SCOI 2011]糖果的相关文章

BZOJ 2330 SCOI 2011 糖果

2330: [SCOI2011]糖果 Time Limit: 10 Sec Memory Limit: 128 MB Description 幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求.幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友

CDOJ 435 (SCOI 2011) 糖果 Label:差分约束系统

糖果 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 131072/131072KB (Java/Others) Submit Status 幼儿园里有NN个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求.幼儿园的糖果总是有限的,lxhgww想知道他至少需

BZOJ 2330 SCOI 2011 糖果 差分约束系统

题目大意:幼儿园老师给小盆友们发糖果.有5种要求,问老师最少需要准备多少糖果.如不能满足,输出-1. 思路:裸地差分约束系统,但是正向加边会T,需要反向加边. CODE: #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 400010 using namespace std; int

解题:SCOI 2011 糖果

题面 能把差分约束卡死的题,因为正解并不是差分约束 1 #include<queue> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 const int N=100005; 8 int p[N],noww[2*N],goal[2*N],val[2*N]; 9 int vis[N],in

BZOJ 2333 SCOI 2011 棘手的操作 可并堆

做此题的原因 题号美 题目大意 给出一个序列,支持一堆操作(具体看下面).让你维护它. 思路 U x y:我们需要可并堆来将两个堆合并. A1 x v:将这个点从堆中拽出来,改了之后再合并回去. A2 x v:在堆顶打标记. A3:记录一个全局变量记录. F1 x:将这个点到堆顶的链上的所有标记下传,之后返回自己的大小. F2 x:返回堆顶. F3:用一个堆(set也行)维护所有堆顶的元素.需要仔细讨论一下. CODE #define _CRT_SECURE_NO_WARNINGS #inclu

【学习】差分约束

今天%你赛考了差分约束相关,于是发现又有忘了的东西,复习 0x00 差分约束 差分约束是求解N元一次特殊不等式组的一种方法.差分约束系统包含$N$个变量和$M$个约束条件,每个约束条件都是一个关于其中两个变量的一个一次不等式 ,每个不等式形如$x[i]-x[j]≤a[k]$,$x[i],x[j]$为变量,$a[k]$为常数. 引理:若${Xi}$为差分约束系统的一组解,$?$为任意常数,那么${Xi+?}$也是一组解. 0x10 最短路 差分约束系统中的每个不等式都与最短路中的三角形不等式$di

C++之路进阶——差分约束(糖果)

2404 糖果 2011年省队选拔赛四川 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求.幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到

vijos1325 桐桐的糖果计划

Description 桐桐是一个快乐的小朋友,他生活中有许多许多好玩的事,让我们一起来看看吧-- 桐桐很喜欢吃棒棒糖.他家处在一大堆糖果店的附近. 但是,他们家的区域经常出现塞车.塞人等情况,这导致他不得不等到塞的车或人走光了他才能去买到他最爱吃的棒棒糖品种.于是,他去找市长帮他修路,使得每两个糖果店之间至少有两条完全不同的路.可是市长经费有限,于是让桐桐找出哪些路被塞住后会使某些糖果店与糖果店间无法到达及最少的修路条数.你能帮助他吃到他最喜爱的糖果吗? 注:1->3->2  和 1->

别把糖果撒给路人 枪口对准家人

别把糖果撒给路人,枪口对准家人 01 在书里读过很多尖酸刻薄的人,他们对任何人都不够友好,不够温和.但是或许是自己生活的圈子太小了,现实生活中还没有遇到几个身上长着隐形的刺的人.所以也总觉得那些人只是为了丰富故事内容而捏造出来的角色. 然而后来却慢慢发现,每个人都是多面的.有些人对待朋友同事甚至对待陌生人,都温文尔雅,而把生活的不如意全都压在心里,他们总要找到一个发泄的出口,不伤害路人,也只能回家爆发,伤害家人了. 家人会包容你的所有,与你一起分担生活的苦,但是很多事情包括亲情在内,都要有个度.