POJ--3159[Candies] 差分约束

47 篇文章 1 订阅
45 篇文章 0 订阅

题目意思:
flymouse是幼稚园班上的班长,一天老师给小朋友们买了一堆的糖果,由flymouse来分发,在班上,
flymouse和snoopy是死对头,两人势如水火,不能相容,因此fly希望自己分得的糖果数尽量多于
snoopy,而对于其他小朋友而言,则只希望自己得到的糖果不少于班上某某其他人就行了。

比如A小朋友强烈希望自己的糖果数不能少于B小朋友m个,即B- A<=m,A,B分别为
A、B小朋友的分得的糖果数。这样给出若干组这样的条件,要使fly最后分得的糖果数s1和snoopy
最后分得的糖果数s2差别取到最大!即s2-s1取最大.

因此根据题意,可以列出如下的不等式:
  
    Sbi-Sai<=ci(1=<i<=n)             
  
最终要使得Sn-S1最大;

其实就是一个差分约束系统。
求最短路时用到的三角形不等式中,最终对于每条有向边(u,v)有: d[v]<=d[u]+w(u,v);
将Sbi-Sai<=ci变成Sbi<=Sai+ci;就跟上式的形式相似。

在最短路的松弛过程中每次都是 if(d[v]>d[u]+w(u,v)) then d[v]<=d[u]+w(u,v);
则最后不断的松弛,使得对所有边 d[v]<=d[u]+w(u,v);
对于Sbi<=Sai+ci;通过做bellmanford,Sbi通过不断的松弛,由正的无穷不断减小,直到所有的
约束条件都的到满足,所以这时的求出的Sbi是满足约束条件的最大的一组解!!
这样最后的结果就是Sn-S1,初始时将S1设为0,则最后的结果就是Sn的值!
不过直接用bellman-ford复杂度高了点!用队列优化的bellman-ford即spfa可以承受!

 

CODE:

/*差分约束*/
/*AC代码:469ms*/
#include <iostream>
#define MAXN 30005
#define INF 0x7fffffff
struct edge
{
	int v,w,next; 
}E[150005];
int head[MAXN],ecnt;
int Stack[MAXN],dis[MAXN];
bool Instack[MAXN];
int N,M,top;
void Insert(int u,int v,int w)
{
	E[ecnt].v=v;
	E[ecnt].w=w;
	E[ecnt].next=head[u];
	head[u]=ecnt++; 
}
void Init()
{
	int i,u,v,w;
	memset(head,-1,sizeof(head));ecnt=0;
	for(i=1;i<=M;i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		Insert(u,v,w);//v-u<=w;
	}
}
int SPFA()
{
	int i,u,v,w;
	memset(Instack,false,sizeof(Instack));
	for(i=1;i<=N;i++)
		dis[i]=INF;
	top=0;
	Stack[top++]=1;
	Instack[1]=true;
	dis[1]=0;
	while(top)
	{
		u=Stack[--top];
		Instack[u]=false;
		for(i=head[u];i!=-1;i=E[i].next)
		{
			v=E[i].v;w=E[i].w;
			if(dis[v]>dis[u]+w)
			{
				dis[v]=dis[u]+w;
				if(!Instack[v])
				{
					Stack[top++]=v;
					Instack[v]=true;
				}
			}
		}
	}
	return dis[N]; 
}
int main()
{
	while(scanf("%d%d",&N,&M)!=EOF)
	{
		Init();
		int ans=SPFA();
		printf("%d\n",ans);
	}
return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__简言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值