• 刷题总结——分糖果(bzoj2330)


    题目:

    Description

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

    Input

    输入的第一行是两个整数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个小朋友分到的糖果;

    Output

    输出一行,表示lxhgww老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出-1。

    Sample Input

    5 7

    1 1 2

    2 3 2

    4 4 1

    3 4 5

    5 4 5

    2 3 5

    4 5 1

    Sample Output

    11

    HINT

    【数据范围】
    对于30%的数据,保证 N<=100
    对于100%的数据,保证 N<=100000
    对于所有的数据,保证 K<=100000,1<=X<=5,1<=A, B<=N

    题解:

      差分约束模板题目·····只是注意怎样处理等于的情况就可以了

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int N=1e5+5;
    queue<int>que;
    int first[N],next[N*5],go[N*5],val[N*5],tot=1;
    int cnt[N],n,k;
    long long dis[N];
    bool insta[N];
    inline void comb(int a,int b,int c)
    {
      next[++tot]=first[a],first[a]=tot,go[tot]=b,val[tot]=c;
    }
    inline bool spfa()
    {
      insta[0]=true,cnt[0]=1;
      que.push(0);
      while(!que.empty())
      {
        int u=que.front();
        que.pop();
        insta[u]=false;
        for(int e=first[u];e;e=next[e])
        {
          int v=go[e];
          if(dis[v]<dis[u]+val[e])
          {
            dis[v]=dis[u]+val[e];      
            if(!insta[v])
            {
              cnt[v]++;
              if(cnt[v]==n+1)  return false; 
              insta[v]=true,que.push(v);
            }
          }
        }
      }
      return true;
    }
    int main()
    {
      //freopen("a.in","r",stdin);
      scanf("%d%d",&n,&k);
      int a,b,x;
      for(int i=1;i<=k;i++)
      {
        scanf("%d%d%d",&x,&a,&b);
        if(x==1)
        {
          comb(a,b,0);
          comb(b,a,0);
          continue;
        }
        if(x==2)
        {
          if(a==b)
          {
            cout<<"-1"<<endl;
            return 0;
          }
          comb(a,b,1);
          continue;
        }
        if(x==3)
        {
          comb(b,a,0);
          continue;
        }
        if(x==4)
        {
          if(a==b)
          {
            cout<<"-1"<<endl;
            return 0;
          }
          comb(b,a,1);
          continue;
        }
        if(x==5)
        {
          comb(a,b,0);
          continue;
        }
      }
      for(int i=n;i>=1;i--)  
        comb(0,i,1);
      if(spfa())
      {
        long long ans=0;
        for(int i=1;i<=n;i++)
          ans+=dis[i];
        cout<<ans<<endl;
      }
      else
        cout<<"-1"<<endl;
      return 0;
    }
  • 相关阅读:
    网络流24题题解
    NOIP2018游记
    AGC016题解
    雅礼集训总结
    数学相关【真·NOIP】
    NOIP2018系列
    洛咕P4180 严格次小生成树
    矩阵乘法学习笔记
    一些比较神奇的思路
    点分治复习记
  • 原文地址:https://www.cnblogs.com/AseanA/p/7473547.html
Copyright © 2020-2023  润新知