題意:
一堆牛在一條直線上按編號站隊,在同一位置可以有多頭牛並列站在一起,但編號小的牛所佔的位置不能超過編號大的牛所佔的位置,這裡用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 99999999using 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");elseprintf("%d\n",dis[N]); }int main(){while(scanf("%d%d%d",&N,&ML,&MD)!=EOF){Init();Bellman_Ford();}return 0;}
CODE(2):