zoukankan      html  css  js  c++  java
  • 【洛谷P3275】糖果【差分约束】【负环】

    题目大意:

    题目链接:https://www.luogu.org/problemnew/show/P3275
    nn个小朋友和mm个要求,其中要求的格式如下:

    • 1 A B1 A B, 表示第 AA 个小朋友分到的糖果必须和第 BB 个小朋友分到的糖果一样多;
    • 2 A B2 A B, 表示第 AA 个小朋友分到的糖果必须少于第 BB 个小朋友分到的糖果;
    • 3 A B3 A B, 表示第 AA 个小朋友分到的糖果必须不少于第 BB 个小朋友分到的糖果;
    • 4 A B4 A B, 表示第 AA 个小朋友分到的糖果必须多于第 BB 个小朋友分到的糖果;
    • 5 A B5 A B, 表示第 AA 个小朋友分到的糖果必须不多于第 BB 个小朋友分到的糖果;

    求至少要多少个糖果使得每个小朋友都可以分到糖果并且所有要求都满足。


    思路:

    这道题的查封约束十分的明显。可以直接列出来:

    1. 需要满足x=yx=y,为了写成abaleq b的形式,可以改成xyxleq yyxyleq x
    2. 需要满足x<yx< y,也就是说ay1aleq y-1
    3. 需要满足xyxgeq y,直接反过来变成yxyleq x即可
    4. 需要满足x>yx>y,即xy+1xgeq y+1,移项得yx1yleq x-1
    5. 需要满足xyxleq y,不解释了

    对于连边方式2和4需要特判,如果x=yx=y那么明显是不成立的。
    但是这道题很奇怪,负权+跑最短路+判负环只能拿70分。改成正权+最长路+判正环才可以。
    而且第六个点明显是卡了spfaspfa的,add(0,i,0)(i=1n)add(0,i,0)(i=1sim n)会被卡T。其实应该是可以随机连边的,应该可以过掉,但是看到说add(0,i,0)(i=n1)add(0,i,0)(i=nsim1)就可以过就没有随机了。
    总之一道神题orz就对了。


    代码:

    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    
    const int N=100010;
    const int M=300010;
    int n,m,tot,x,y,z;
    int head[N],cnt[N];
    ll dis[N],ans,minn;
    bool vis[N];
    
    struct edge
    {
    	int to,next;
    	ll dis;
    }e[M];
    
    void add(int from,int to,ll dis)
    {
    	e[++tot].to=to;
    	e[tot].dis=dis;
    	e[tot].next=head[from];
    	head[from]=tot;
    }
    
    bool spfa()
    {
    	memset(dis,0xcf,sizeof(dis));
    	memset(vis,0,sizeof(vis));
    	queue<int> q;
    	q.push(0);
    	vis[0]=1;
    	dis[0]=0;
    	cnt[0]=1;
    	while (q.size())
    	{
    		int u=q.front(),v;
    		q.pop();
    		vis[u]=0;
    		for (int i=head[u];~i;i=e[i].next)
    		{
    			v=e[i].to;
    			if (dis[v]<dis[u]+e[i].dis)  //最长路
    			{
    				dis[v]=dis[u]+e[i].dis;
    				cnt[v]=cnt[u]+1;
    				if (cnt[v]>n+1) return 0;
    				if (!vis[v])
    				{
    					q.push(v);
    					vis[v]=1;
    				}
    			}
    		}
    	}
    	return 1;
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&z,&x,&y);
    		if (z%2==0&&x==y) return !printf("-1");  //特判,我大于我自己
    		if (z==1) add(x,y,0),add(y,x,0);
    		if (z==2) add(x,y,1);
    		if (z==3) add(y,x,0);
    		if (z==4) add(y,x,1);
    		if (z==5) add(x,y,0);
    	}
    	for (int i=n;i>=1;i--)
    		add(0,i,0);
    	minn=2147483647;
    	if (spfa())
    	{
    		for (int i=1;i<=n;i++)
    		{
    			minn=min(minn,dis[i]);
    			ans+=dis[i];
    		}
    		printf("%lld
    ",ans-(minn-1)*(ll)n);
    	}
    	else printf("-1");
    	return 0;
    }
    
  • 相关阅读:
    MySQL主从复制故障1595报错【原创】
    深入理解计算机系统(3.1)------汇编语言和机器语言
    深入理解计算机系统(2.7)------浮点数舍入以及运算
    深入理解计算机系统(2.7)------二进制小数和IEEE浮点标准
    深入理解计算机系统(2.6)------整数的运算
    深入理解计算机系统(2.5)------C语言中的有符号数和无符号数以及扩展和截断数字
    深入理解计算机系统(2.4)------整数的表示(无符号编码和补码编码)
    Spring详解(七)------AOP 注解
    深入理解计算机系统(2.3)------布尔代数以及C语言运算符
    深入理解计算机系统(2.2)------进制间的转换原理
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998317.html
Copyright © 2011-2022 走看看