糖果

https://loj.ac/problem/2436

题目描述

  有n个小朋友,共有k个要求,求满足要求的最少的糖果数。

思路

  显然的差分约束题,对于每个条件分别建边即可(假设第i个小朋友分到的糖果数为x[i]):

  ①x=1时,令x[a]≥x[b],x[b]≥x[a],即满足x[a]=x[b]。

  ②x=2时,x[a]<x[b],由于糖果数必定是整数,因此x[a]≤x[b]-1。

  ③x=3时,x[a]≥x[b]。

  ④x=4时,同理,x[a]≥x[b]+1。

  ⑤x=5时,x[a]≤x[b]。

  按此约束条件建出图后在图上跑spfa即可,注意判断是否存在负环。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10,M=2e5+10;
int nxt[M],to[M],w[M],head[N],tot;
int dis[N],in[N],n,maxe;
bool exist[N];
void add_edge(int x,int y,int v)
{
    nxt[++tot]=head[x];
    head[x]=tot;
    to[tot]=y;
    w[tot]=v;
}
void end()
{
    printf("-1");
    exit(0);
}
void spfa()
{
    queue<int>q;
    for(int i=1;i<=n;i++)
        q.push(i),exist[i]=1,dis[i]=1,in[i]=1;
    while(!q.empty())
    {
        int u=q.front();q.pop();
        exist[u]=0;
        for(int i=head[u];i;i=nxt[i])
        {
            int v=to[i];
            if(dis[v]<dis[u]+w[i])
            {
                dis[v]=dis[u]+w[i];
                in[v]++;
                if(in[v]>=n)end();
                if(!exist[v])
                {
                    exist[v]=1;
                    q.push(v);
                }
            }
        }
    }
}
int main() 
{
    int k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=k;i++)
    {
        int x,a,b;
        scanf("%d%d%d",&x,&a,&b);
        if(x==1)add_edge(a,b,0),add_edge(b,a,0);
        else if(x==2)add_edge(a,b,1);
        else if(x==3)add_edge(b,a,0);
        else if(x==4)add_edge(b,a,1);
        else add_edge(a,b,0);
        if((x==2||x==4)&&a==b)end();
    }
    spfa();
    long long ans=0;
    for(int i=1;i<=n;i++)
        ans+=dis[i];
    printf("%lld",ans);
}

 

posted @ 2019-10-22 18:15  fbz  阅读(125)  评论(0编辑  收藏  举报