题意:
一堆牛在一条直线上按编号站队,在同一位置可以有多头牛并列站在一起,但编号小的牛所占的位置不能超过编号大的牛所占的位置,这里用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):