POJ--3169[Layout] 基础的差分约束

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

题意:

一堆牛在一条直线上按编号站队,在同一位置可以有多头牛并列站在一起,但编号小的牛所占的位置不能超过编号大的牛所占的位置,这里用d[i]表示编号为i的牛所处的位置,即要满足d[i]-d[i+1]<=0,同时每两头牛之间有以下两种关系(对于输入的a b d来说):
            1>如果是喜欢关系:即需要满足d[b]-d[a]<=d
            2>如果是讨厌关系:即需要满足d[b]-a[a]>=d ……> d[a]-d[b]<=-d
   由于题目要求队伍的最大可能长度,即求满足以下三个约束条件的最大值,,由于此处是求最大值,故用Bellman_Ford算法求约束图的最短路径.
            1>对于ML有:d[b]-d[a]<=d
            2>对于MD有:d[a]-d[b]<=-d
            3>对于n个顶点的约束图有:s[i]-s[i+1]<=0
    题目的解为:有负环输出-1,d[n]无穷大输出-2,其他输出dist[n].
    在差分约束系统中如果题目要求是求最小值,就将约束条件转化为">="形式,然后用Bellman_Ford算法求解约束图的最长路径,如果题目要求的是最大值,就将约束条件转化为"<="形式,然后用Bellman_Ford算法求解约束图的最短路径.

 

PS:
(1)INF不能开得太大,可能会溢出;
(2)数组尽量开小,不然会比较慢

 

CODE(1):Bellman_ford

/*差分约束(Bellman_Ford)*/
/*AC代码:32ms*/
#include <iostream>
#define MAXN 1005
#define INF 99999999
using namespace std;
struct edge
{
	int u,v,w; 
}E[30000];
int ecnt;
int dis[MAXN];
int N,ML,MD;
void Insert(int u,int v,int w)
{
	E[ecnt].v=v;
	E[ecnt].w=w;
	E[ecnt].u=u;
	ecnt++; 
}
void Init()
{
	int i,u,v,w;
	ecnt=0;
	for(i=1;i<=ML;i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		Insert(u,v,w); 
	}
	for(i=1;i<=MD;i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		Insert(v,u,-w);
	}
	for(i=1;i<N;i++)
		Insert(i+1,i,0);
}
void Bellman_Ford()
{
	int i,j;
	for(i=1;i<=N;i++)
		dis[i]=INF;
	dis[1]=0;
	bool flag;
	for(i=1;i<N;i++)
	{
		flag=false;
		for(j=0;j<ecnt;j++)
		{
			if(dis[E[j].v]>dis[E[j].u]+E[j].w)
			{
				flag=true;
				dis[E[j].v]=dis[E[j].u]+E[j].w;
			}
		}
		if(!flag) break;
	}
	for(j=0;j<ecnt;j++)
		if(dis[E[j].v]>dis[E[j].u]+E[j].w)
		{printf("-1\n");return;}
	if(dis[N]==INF) 
		printf("-2\n");
	else
		printf("%d\n",dis[N]); 
}
int main()
{
	while(scanf("%d%d%d",&N,&ML,&MD)!=EOF)
	{
		Init();
		Bellman_Ford();
	}
return 0;
}

 

 

CODE(2):

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

__简言

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

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

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

打赏作者

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

抵扣说明:

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

余额充值