P3275 [SCOI2011]糖果

Posted alex-leaves

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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: 复制
5 7
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1
输出样例#1: 复制
11

说明

【数据范围】

对于30%的数据,保证 N<=100

对于100%的数据,保证 N<=100000

对于所有的数据,保证 K<=100000,1<=X<=5,1<=A, B<=N

 

一共五种op,a不大于b就相当于a-b<=0,a小于b相当于a-b<=-1然后最短路,注意判断负环。

AC代码如下:

#include<cstdio>
#include<algorithm>
#include<deque>
using namespace std;
const int N=100000+5;
const int K=100000*3+5;
struct p
{
int to,nxt,w;
}e[K];
int fir[N],nd[N],f[N],n,k,a,b,x,tot;
bool inq[N];
long long ans;
deque<int>q;
void add(int u,int v,int ww)
{
    tot++;
    e[tot].to=v;
    e[tot].w=ww;
    e[tot].nxt=fir[u];
    fir[u]=tot;
    return;
}
void spfa()
{
    nd[0]++;inq[0]=1;
    q.push_back(0);
    while(!q.empty())
    {
        int now=q.front();
        q.pop_front();
        inq[now]=0;
        for(int i=fir[now];i;i=e[i].nxt)
        if(f[e[i].to]>f[now]+e[i].w){
            f[e[i].to]=f[now]+e[i].w;
            if(!inq[e[i].to])
            {
                if(!q.empty()) {
                    if(f[q.front()]>f[e[i].to]) q.push_front(e[i].to);
                    else q.push_back(e[i].to);
                }
                else q.push_back(e[i].to);
                inq[e[i].to]=1;
                nd[e[i].to]++;
                if(nd[e[i].to]>=n) {
                    printf("-1");exit(0);
                }
            }
        }
        
    }
    return;
}
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=n;i>0;i--)
    add(0,i,-1);
    for(int i=1;i<=k;i++)
    {
        scanf("%d%d%d",&x,&a,&b);
        if(x==1) add(a,b,0),add(b,a,0);
        if(x==2) add(a,b,-1);
        if(x==3) add(b,a,0);
        if(x==4) add(b,a,-1);
        if(x==5) add(a,b,0);
        if(x%2==0&&a==b) {printf("-1");return 0;}
    }
    
    f[0]=0;
    spfa();
    for(int i=1;i<=n;i++)
    ans+=-f[i];
    printf("%lld",ans);
    return 0;
}

 

以上是关于P3275 [SCOI2011]糖果的主要内容,如果未能解决你的问题,请参考以下文章

[luogu P3275] [SCOI2011]糖果

Luogu P3275 [SCOI2011]糖果

P3275 [SCOI2011]糖果

P3275 [SCOI2011]糖果

洛谷P3275 [SCOI2011]糖果

题解Luogu P3275 [SCOI2011] 糖果 差分约束