洛谷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

 

思路:

主要考察差分约束,可以通过这篇博文http://www.cnblogs.com/void/archive/2011/08/26/2153928.html了解其基本原理和一些大体的变形

  • 首先就是要根据题目中的不等关系建立有向图。怎么建图?每次将不等关系转化为大于且等于的关系,由后者向前者发出有向边建图。以x=1为例,这时候A和B两个小朋友分配的糖果一样多,那么有A-B=0,B-A=0,这时候分别从A出发,向B建立一条长度为0的边,再从B出发,向A建立一条长度为0的边,表示两者的关系;再如x=2,A的糖果小于B,那么A-B<0,那么有A-B<=-1,那么有B-A>=1,这时候从A出发向B建立一条长度为1的边;其余条件同理。
  • 题目要求:老师至少需要准备的糖果数。即老师给每个学生发的糖要满足题目中的各个约束条件,转化为有向图就是要求有向图的最长路(因为只有最长路都满足了,其余条件才能保证一定满足)。不妨想像一下什么时候题目无解?对,就是图中出现正权环!为了判断正权环,采用SPFA,统计每个节点入队的次数,大于总结点数-1则说明图中有正权环。
  • 同时注意:因为每个人得到的糖果数必须为正,新增加一个节点0,从0向每个人出发引入一条长度为1的边,再通过SPFA统计图中的最长路。
  • 特判:X=2和X=4时,如果A,B两个人的糖果数相同直接输出-1结束。
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
#define mp make_pair
#define int long long
using namespace std;
vector<pair<int,int> >ed[100010];
queue<int> Q;
int n,k;
int vis[100010],dis[100010];
int inq[100010];
int cnt[100010];
int spfa(int v){
    Q.push(v);
    inq[v]=1;
    
    while(!Q.empty()){
        int u=Q.front();
        Q.pop();
        inq[u]=0;        
        cnt[u]++;
        if(cnt[u]>n){//一共有n+1个节点(包括补充的节点0),SPFA每个节点在队列出现的次数不能超过总结点数-1(这里是n)
            return 0;
        }
        for(int i=0;i<ed[u].size();i++){
            int nxt=ed[u][i].first,d=ed[u][i].second;
            if(dis[nxt]<dis[u]+d){
                dis[nxt]=dis[u]+d;
                if(!inq[nxt]){
                    inq[nxt]=1;
                    Q.push(nxt);
                }
            }
        }
    }
    return 1;
}
signed main(){
    scanf("%lld %lld",&n,&k);
    for(int i=0;i<k;i++){
        int x,a,b;
        scanf("%lld %lld %lld",&x,&a,&b);
        if(x==1){ed[a].push_back(mp(b,0));ed[b].push_back(mp(a,0));}
        else if(x==2){ed[a].push_back(mp(b,1));if(a==b){printf("-1\n");return 0;}} //1.特判 
        else if(x==3){ed[b].push_back(mp(a,0));}
        else if(x==4){ed[b].push_back(mp(a,1));if(a==b){printf("-1\n");return 0;}}//1.特判 
        else {ed[a].push_back(mp(b,0));} 
    }
    for(int i=1;i<=n;i++) ed[0].push_back(mp(i,1));
    
    if(!spfa(0)){
        printf("-1\n");
        return 0;
    }
    
    int ans=0;
    for(int i=1;i<=n;i++) ans+=dis[i];
    printf("%lld\n",ans);

    return 0;
}

 

转载于:https://www.cnblogs.com/zhuixunfighting/p/10495441.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
中描述了一个幼儿园里分配糖果的问题,每个小朋友都有自己的要求。问题的输入包括两个整数NN和KK,表示幼儿园里的小朋友数量和要满足的要求数量。接下来的KK行表示小朋友们的要求,每行有三个数字,XX,AA,BB。如果X=1,表示第AA个小朋友分到的糖果必须和第BB个小朋友分到的糖果一样多;如果X=2,表示第AA个小朋友分到的糖果必须少于第BB个小朋友分到的糖果;如果X=3,表示第AA个小朋友分到的糖果必须不少于第BB个小朋友分到的糖果;如果X=4,表示第AA个小朋友分到的糖果必须多于第BB个小朋友分到的糖果;如果X=5,表示第AA个小朋友分到的糖果必须不多于第BB个小朋友分到的糖果。这个问题可以被看作是一个差分约束系统的问题。 具体地说,可以使用差分约束系统来解决这个问题。差分约束系统是一种通过给变量之间的关系添加约束来求解最优解的方法。对于这个问题,我们需要根据小朋友们的要求建立约束条件,并通过解决这个约束系统来得出最小的糖果数量。 在问题的输入中,X的取值范围为1到5,分别对应不同的关系约束。根据这些约束,我们可以构建一个差分约束图。图中的节点表示小朋友,边表示糖果数量的关系。根据不同的X值,我们可以添加相应的边和权重。然后,我们可以使用SPFA算法(Shortest Path Faster Algorithm)来求解这个差分约束系统,找到满足所有约束的最小糖果数量。 需要注意的是,在读取输入时需要判断X和Y是否合法,即是否满足X≠Y。如果X=Y,则直接输出-1,因为这种情况下无法满足约束条件。 综上所述,为了满足每个小朋友的要求,并且满足所有的约束条件,我们可以使用差分约束系统和SPFA算法来求解这个问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【差分约束系统】【SCOI2011糖果 candy](https://blog.csdn.net/jiangzh7/article/details/8872699)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [P3275 [SCOI2011]糖果差分约束板子)](https://blog.csdn.net/qq_40619297/article/details/88678605)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值