題意:給你一排樹,問你最低到最高的最大距離多少?
(1)(行走方式:h1->h2->````hn)其中h1到hn嚴格遞增。
(2)相鄰(高度相鄰)兩樹的距離要<=D。
思路:差分約束
構圖:
(1):相鄰(高度相鄰)兩樹的距離要<=D。
for(i=1;i<N;i++){u=Tnode[i].id;v=Tnode[i+1].id;if(u>v)//d[i]-d[i+1]<=DInsert(i+1,i,D);elseInsert(i,i+1,D); }
(2):相鄰(原始座標相鄰)兩樹的距離要>=1。
for(i=1;i<=N;i++)hash[Tnode[i].id]=i;for(i=1;i<N;i++)Insert(hash[i+1],hash[i],-1);
CODE:
/*差分約束(構圖題)*//*AC代碼:188ms*/#include <iostream>#include <map>#include <cstdlib>using namespace std;#define MAXN 1005#define INF 1e10using namespace std;struct edge{ int v,w,next; }E[3*MAXN];int head[MAXN],ecnt;int Stack[MAXN],cnt[MAXN],dis[MAXN];bool Instack[MAXN];int N,D,scr,sink,top;struct Tree{ int h,id; }Tnode[MAXN];map<int,int>hash;int cmp(const void *p1,const void *p2){ return ((Tree *)p1)->h-((Tree *)p2)->h;}//d[v]<=d[u]+w(u,v);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; memset(head,-1,sizeof(head));ecnt=0;//hash.clear(); for(i=1;i<=N;i++) { scanf("%d",&Tnode[i].h); Tnode[i].id=i; } qsort(Tnode+1,N,sizeof(Tnode[0]),cmp); scr=Tnode[1].id;sink=Tnode[N].id; for(i=1;i<=N;i++) hash[Tnode[i].id]=i; for(i=1;i<N;i++) Insert(hash[i+1],hash[i],-1); for(i=1;i<N;i++) { u=Tnode[i].id; v=Tnode[i+1].id; if(u>v)//d[i]-d[i+1]<=D Insert(i+1,i,D); else Insert(i,i+1,D); }}void SPFA(int scr,int sink){ int i,u,v,w; memset(Instack,false,sizeof(Instack)); memset(cnt,0,sizeof(cnt)); for(i=1;i<=N;i++) dis[i]=INF; top=0; Stack[top++]=scr; Instack[scr]=true; //cnt[scr]=1;//WA的關鍵(是取出後計算的,這樣會多算) dis[scr]=0; while(top) { u=Stack[--top]; Instack[u]=false; cnt[u]++; if(cnt[u]>N) {printf("-1\n");return;} 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]) { Instack[v]=true; Stack[top++]=v; } } } } printf("%d\n",dis[sink]); }int main(){ while(scanf("%d%d",&N,&D)!=EOF) { if(N==0&&D==0) break; Init(); if(scr<sink) SPFA(1,N); else SPFA(N,1); } return 0;}