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


    题目描述

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

    输入

    输入的第一行是两个整数NK

    接下来K行,表示这些点需要满足的关系,每行3个数字,XAB

    如果X=1, 表示第A个小朋友分到的糖果必须和第B个小朋友分到的糖果一样多;

    如果X=2, 表示第A个小朋友分到的糖果必须少于第B个小朋友分到的糖果;

    如果X=3, 表示第A个小朋友分到的糖果必须不少于第B个小朋友分到的糖果;

    如果X=4, 表示第A个小朋友分到的糖果必须多于第B个小朋友分到的糖果;

    如果X=5, 表示第A个小朋友分到的糖果必须不多于第B个小朋友分到的糖果;

    输出

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

    样例输入

    5 7
    1 1 2
    2 3 2
    4 4 1
    3 4 5
    5 4 5
    2 3 5
    4 5 1

    样例输出

    11


    题解

    差分约束系统

    把所有的约束转化为两个点之间连边,用spfa处理。

    具体地,x<y:x->y(1),x≤y:x->y(0),x==y:x<->y(0)

    由于每个数都为正,再加S->i(1)。

    然后跑最长路即可。

    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    typedef long long ll;
    queue<int> q;
    int head[100010] , to[300010] , next[300010] , cnt , inq[100010] , num[100010];
    ll dis[100010] , len[300010];
    void add(int x , int y , ll z)
    {
    	to[++cnt] = y;
    	len[cnt] = z;
    	next[cnt] = head[x];
    	head[x] = cnt;
    }
    int main()
    {
    	int n , k , t , x , y , i;
    	ll ans = 0;
    	scanf("%d%d" , &n , &k);
    	while(k -- )
    	{
    		scanf("%d%d%d" , &t , &x , &y);
    		switch(t)
    		{
    			case 1: add(x , y , 0); add(y , x , 0); break;
    			case 2: add(x , y , 1); break;
    			case 3: add(y , x , 0); break;
    			case 4: add(y , x , 1); break;
    			default: add(x , y , 0);
    		}
    	}
    	for(i = 1 ; i <= n ; i ++ ) dis[i] = 1 , inq[i] = 1 , q.push(i);
    	while(!q.empty())
    	{
    		x = q.front() , q.pop() , inq[x] = 0;
    		for(i = head[x] ; i ; i = next[i])
    		{
    			if(dis[to[i]] < dis[x] + len[i])
    			{
    				dis[to[i]] = dis[x] + len[i];
    				if(!inq[to[i]])
    				{
    					if(num[to[i]] >= n)
    					{
    						printf("-1
    ");
    						return 0;
    					}
    					num[to[i]] ++ , inq[to[i]] = 1 , q.push(to[i]);
    				}
    			}
    		}
    	}
    	for(i = 1 ; i <= n ; i ++ ) ans += dis[i];
    	printf("%lld
    " , ans);
    	return 0;
    }

     

  • 相关阅读:
    5分钟了解为什么学习Go
    jieba gensim 相似度实现
    functiils.lru_cache缩短递归时间
    python深浅copy和赋值
    ajax上传文件 基于jquery form表单上传文件
    form组件类 钩子函数验证
    基于jquery读取input上传的文件内容
    MongonDB指令汇总
    冥想编程
    《如何阅读一本书》读书笔记
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/6617326.html
Copyright © 2020-2023  润新知