bzoj2330 [SCOI2011]糖果题解

http://www.lydsy.com/JudgeOnline/problem.php?id=2330

  • 题目大意

    对这个题我真的不想再多提一句了。

    n个人分糖,保证每个人都有糖,有k个限制条件,分别是a=b,a<b,a≥b,a>b,a≤b。这五种情况分别用x=1,2,3,4,5表示。求最少需要准备多少糖果。其中n,k≤106。

  • 题解

    一看就是差分约束了。

    差分约束中求最小值用≥,跑最长路;求最大值用≤,跑最短路。

    x=1即a=b,直接a→b,b→a权值都是0;

    x=3即a≥b,直接b→a,权值为0;

    x=5即a≤b,直接a→b,权值为0;

    那么不带等号的怎么办呢?

    (如果是实数可以不管,就是求得的最值取不到也在误差范围内。)

    因为a,b均是整数,所以

    x=2即a<b?a≤b?1,然后a→b,权值为1;

    同理,x=4即a>b?a≥b+1,然后b→a,权值为1;

    然后是与源点0连边。因为每个人都有糖,即f[i]≥1?f[i]?f[0]≥1,所以0→i,权值为1。

  • 注意事项

    本来是一道很裸的差分约束,但是:

    某测试点是十万条边连成一条链,如果采用邻接表从表头插入的写法,从源点0连边时如果i=1→n,会T掉,应该i=n→1;

    某测试点是x=2或4时出现了a=b的情况,即a>a或a<a,这种情况应为无解,输出-1,如果不特判,你的spfa将会在毫不知情的情况下陷入死循环(就是邻接表自己连成环了);

    dist数组要开longlong。

  • Code
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 100010, oo = 1000000000, nil = 0;
int n, k;
int e, pnt[maxn], nxt[maxn << 2], u[maxn << 2], v[maxn<< 2], w[maxn << 2];
bool vis[maxn], flag;
int times[maxn];
long long d[maxn];
void addedge(int a, int b, int c)
{
    u[++e] = a; v[e] = b; w[e] = c;
    nxt[e] = pnt[a]; pnt[a] = e;
}
void init()
{
    int x, a, b;
    flag = false;
    scanf("%d%d", &n, &k);
    //跑最长路的时候我喜欢直接把边权加成负的
    for(int i = n; i > 0; --i)
    {
        addedge(0, i, -1);
    }
    for(int i = 1; i <= k; ++i)
    {
        scanf("%d%d%d", &x, &a, &b);
        switch(x)
        {
            case 1: addedge(a, b, 0);
                    addedge(b, a, 0);
                    break;
            case 2: addedge(a, b, -1);
                    if(a == b)
                    {
                        flag = true;
                    }
                    break;
            case 3: addedge(b, a, 0);
                    break;
            case 4: addedge(b, a, -1);
                    if(a == b)
                    {
                        flag = true;
                    }
                    break;
            case 5: addedge(a, b, 0);
                    break;
            default:break;
        }
    }
}
void work()
{
    if(flag)
    {
        puts("-1");
        return;
    }
    memset(d, 0x7f, sizeof(d));
    memset(vis, 0, sizeof(vis));
    memset(times, 0, sizeof(times));
    queue <int> Q;
    d[0] = 0;
    vis[0] = true;
    ++times[0];
    Q.push(0);
    while(!Q.empty())
    {
        int t = Q.front();
        Q.pop();
        vis[t] = false;
        for(int j = pnt[t]; j != nil; j = nxt[j])
        {
            if(d[v[j]] > d[t] + w[j])
            {
                d[v[j]] = d[t] + w[j];
                if(!vis[v[j]])
                {
                    vis[v[j]] = true;
                    ++times[v[j]];
                    Q.push(v[j]);
                    //因为加入了点“0”,所以总共有n+1个点
                    //某点第n+1次入队时才说明有负环
                    //虽然这里写>=n也能过
                    if(times[v[j]] > n)
                    {
                        puts("-1");
                        return;
                    }
                }
            }
        }
    }
    long long ans = 0;
    for(int i = 1; i <= n; ++i)
    {
        ans += d[i];
    }
    printf("%lld\n", -ans);
}
int main()
{
    init();
    work();
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-08 20:47:23

bzoj2330 [SCOI2011]糖果题解的相关文章

差分约束详解&amp;&amp;锣鼓SCOI2011糖果题解

差分约束系统: 如果一个系统由n个变量和m个约束条件组成,形成m个形如ai-aj≤k的不等式(i,j∈[1,n],k为常数),则称其为差分约束系统(system of difference constraints).亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法. ——度娘. 然而并没有看懂.. 通俗来说,满足差分约束的条件是题目中给了你多个ai-aj<=(>=,<,>之类)的条件,要求同时满足这些条件并求极值的问题. 内么,怎么同时满足这些问题呢? 假如我们以这个东西为

BZOJ2330[SCOI2011]糖果

差分约束第二题 传送门: 这个的模型很清楚,具体的建模可以参考代码. 一个需要注意的点.如果题目中有d[i]==d[j]的地方,只需要连两个边权为0的双向边就行了. 1 //BZOJ 2330 2 //by Cydiater 3 //2016.9.1 4 #include <iostream> 5 #include <cstdio> 6 #include <cstring> 7 #include <string> 8 #include <algorit

bzoj2330: [SCOI2011]糖果 差分约束

这题有毒.首先显然是差分约束裸题,然而n,m<=1e5,并且有两个数据如下: 1.有负环的大数据.由于spfa判负环是o(nm)的,所以这个点要跑5s.然而这个点存在负的自环,可以直接判掉…… 2.1->2->...->n的一条链.若1先入队,则可以一次更新完.否则每次编号较小的点会把所有编号大于它的点都重新更新一次,就卡到了o(n^2).若一般的边表按1->n加边,入队顺序就是n->1.面向数据地,可以倒着加边,或者按1->n先把所有点入队. 有一个tarjan

[BZOJ2330]SCOI2011糖果|差分约束

差分约束题..学了一下差分约束,我觉得还是挺简单的,考虑f[u]-f[v]<=c,发现和最短路的松弛操作神似,最短路跑完之后对于一条边(v,u),显然有d[u]<=d[v]+c,不就是上面差分约束的式子吗..那就转化成最短(长)路做咯,以最短路为例了,对于每个f[u]-f[v]<=c,连一条v到u权值为c的边,然后跑最短路,如果有负环那就说明无解,没有的话跑完之后各点的d值就是解.. 对于本题,d[a]==d[b],有 d[a]-d[b]>=0, d[b]-d[a]>=0 d

【bzoj2330】: [SCOI2011]糖果 图论-差分约束-SPFA

[bzoj2330]: [SCOI2011]糖果 恩..就是裸的差分约束.. x=1 -> (A,B,0) (B,A,0) x=2 -> (A,B,1)  [这个情况加个A==B无解的要特判] x=3 -> (B,A,0)  [恩这个是不少于一开始zz建反了] x=4 -> (B,A,1) x=5 -> (A,B,0) 然后源点到所有点建1的边[恩据说有条链所以要反着连]跑最长路就好了 1 /* http://www.cnblogs.com/karl07/ */ 2 #inc

差分约束 【bzoj2330】[SCOI2011]糖果

/*[bzoj2330][SCOI2011]糖果 2014年3月5日1,2761 Description 幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求.幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求. Input 输入的第

BZOJ2330 糖果题解 查分约束

BZOJ 2330 糖果题解 差分约束系统 + SPFA 题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2330 Description 幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求.幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多

2330: [SCOI2011]糖果

2330: [SCOI2011]糖果 Description 幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求.幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求. Input 输入的第一行是两个整数N,K. 接下来K行,表示这些

【差分约束】SCOI2011糖果

P3275 [SCOI2011]糖果 快noip了我还在干什么啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 来我们看这道题 根据条件建图, 因为求得是最小值, 所以要跑最长路qwq(这是我记住的QAQ 不想写了让我们直接看看题解吧! 快noip了我还在干什么啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 来我们看这道题 根据条件建图, 因为求得是最小值, 所以要跑最长路qwq(这是我记住的QAQ 不想写了让我们直接看看题解吧! P3275 [SCOI2011]糖果(five20的题解) 有环代表条