【解题报告】洛谷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
原文地址:https://www.cnblogs.com/wweiyi2004/p/15371897.html