zoukankan      html  css  js  c++  java
  • 【解题报告】洛谷P3275 糖果

    【解题报告】洛谷P3275 糖果

    原题链接

    https://www.luogu.com.cn/problem/P3275

    思路

    在这样天气寒冷的日子里,怎么能不做题呢~!

    天气阴凉,我怀着激动的心情打开了这道题目

    题意大概满足一堆要求,让你求一个满足要求的所有的变量的和

    自己看去吧

    然后我们读题发现,这不就是一个差分约束吗?

    待会?

    差分约束满足的形式是这样的

    [x_i-x_{i'} le y_i ]

    所以题目中不少于不多于的都非常好搞,直接连边就可以了

    那剩下的怎么搞呢?

    首先等于,等于的话我们可以双向连边,一个不大于,一个不小于,不就是等于了吗?

    然后后面呢?

    我们实际上可以他们变成 (A le B-1) , (B le A-1) 之类的,这样就可以实现小于了,具体这样做的原因是因为 (A,B) 只能是整数啊喂

    然后我们用一个 (SPFA) 跑就可以了

    有一个玄学的东西,就是我们在跑的时候要对于超级源点从大边向小边连边,不然会被卡掉,或者连边的同时把连得边都 push 一下也可以似乎?

    我不知道为啥,但是我过了

    别人也不知道为啥,我就写在了这里qaq

    std

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <queue>
    #define int long long
    using namespace std;
    const int maxn=300005;
    inline int read()
    {
    	int x=0,f=1;
    	char c=getchar();
    	while(c<'0'||c>'9')
    	{
    		if(c=='-')
    		f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9')
    	{
    		x=(x<<1)+(x<<3)+c-'0';
    		c=getchar();
    	}
    	return x*f;
    }
    struct edge{
    	int e,next,val;
    }ed[maxn<<1];
    int en,first[maxn];
    void add_edge(int s,int e,int val)
    {
    	en++;
    	ed[en].next=first[s];
    	first[s]=en;
    	ed[en].e=e;
    	ed[en].val=val;
    }
    int n,k;
    int d[maxn],num[maxn];
    bool vis[maxn];
    queue <int> q;
    bool spfa(int s)
    {
    	d[s]=0;
    	vis[s]=true;
    	q.push(s);
    	num[s]++;
    	while(q.size())
    	{
    		int x=q.front();
    		q.pop();
    		vis[x]=false;
    		for(int i=first[x];i;i=ed[i].next)
    		{
    			int e=ed[i].e;
    			int val=ed[i].val;
    			if(d[e]<d[x]+val)
    			{
    				d[e]=d[x]+val;
    				if(!vis[e])
    				{
    					vis[e]=true;
    					q.push(e);
    					num[e]++;
    					if(num[e]==n+1) return false;
    				}
    			}
    		}
    	}
    	return true;
    }
    signed main()
    {
    	memset(d,-0x3f3f3f,sizeof(d));
    	n=read(),k=read();
    	for(int i=1;i<=k;i++)
    	{
    		int x=read(),a=read(),b=read();
    		if(x==1)
    		{
    			add_edge(b,a,0);//a<=b
    			add_edge(a,b,0);//a>=b;
    		}
    		else if(x==2)
    		{
    			if(a==b)
    			{
    				cout<<-1<<'
    ';
    				return 0;
    			}
    			add_edge(a,b,1);//a<b
    		}
    		else if(x==3)
    		{
    			add_edge(b,a,0);//a>=b
    		}
    		else if(x==4)
    		{
    			if(a==b)
    			{
    				cout<<-1<<'
    ';
    				return 0;
    			}
    			add_edge(b,a,1);//a>b
    		}
    		else if(x==5)
    		{
    			add_edge(a,b,0);//a<=b
    		}
    	}
    	for(int i=n;i>=1;i--)
    	add_edge(0,i,1);//q.push(i);
    	if(!spfa(0))
    	{
    		cout<<-1<<'
    ';
    		return 0;
    	}
    	int ans=0;
    	for(int i=1;i<=n;i++)
    	ans+=d[i];
    	cout<<ans<<'
    ';
    	return 0;
    }
    
    本博文为wweiyi原创,若想转载请联系作者,qq:2844938982
  • 相关阅读:
    .Net Mvc 基于Filter实现对权限的扩展定制
    VS 2015 远程调试
    SVN 创建版本库
    .NET 调用支付宝沙箱接口
    selenium常用总结
    Python常用小技巧
    Centos7 安装Mysql 5.7
    Sqlserver 递归查询
    Sqlserver 中case when 的详细用法总结
    Asp.NetCoreWebApi入门
  • 原文地址:https://www.cnblogs.com/wweiyi2004/p/15371897.html
Copyright © 2011-2022 走看看