spfa+差分约束系统(C - House Man HDU - 3440 )+对差分约束系统的初步理解
题目链接:https://cn.vjudge.net/contest/276233#problem/C
题目大意:有n层楼,给你每个楼的高度,和这个人单次的最大跳跃距离m,两个楼之间的距离最小是1,但是楼和楼之间的距离是能够调整的,现在有一个人,要从最矮的楼开始跳,每一次跳到比当前的楼高的楼上,然后问你在将所有的楼都走一遍的基础上,从第一个楼到最后一个楼之间的最远距离是多少?
思路:使用差分约束系统的相关知识, 我们可以建立如下不等式。
1,当相邻的时候,限制posA-posB>=1,也就是posB-posA<=-1。
2,当按照高度依次建立边的时候,我们就限制posA-posB<=m。这样的根据这两个式子就可以建立图了。
注意点:我们在建立相邻点的时候,是按照从小到大进行建边的,所以在对于第二种情况的时候,我们应该是先判断两个位置的大小,再去建边。
对差分约束系统的初步理解:如果是和spfa有关的话,具体就是建立不等式,然后如果求最大差值的话,我们直接将变建立成这两个点的最大差值就可以了。然后在跑最短路的过程中,就是找满足从posA到posB的所有不等式当中的最小的哪一个,因为求出来的值是要满足这两个点的所有不等式的。
AC代码:
1 #include<iostream> 2 #include<cstring> 3 #include<stack> 4 #include<iomanip> 5 #include<cmath> 6 #include<queue> 7 #include<algorithm> 8 #include<stdio.h> 9 using namespace std; 10 # define ll long long 11 # define inf 1ll<<60 12 const int maxn = 1000+100; 13 const int maxedge= 1000000+10; 14 int n; 15 ll m; 16 int num,head[maxn]; 17 ll dis[maxn]; 18 int out[maxn],vis[maxn]; 19 struct node 20 { 21 int fr; 22 int to; 23 ll cost; 24 int nex; 25 } edge[maxedge]; 26 struct point 27 { 28 int num; 29 int id; 30 } po[maxn]; 31 bool cmp(point t1,point t2) 32 { 33 return t1.num<t2.num; 34 } 35 void init() 36 { 37 for(int i=0; i<=n; i++) 38 { 39 head[i]=-1; 40 out[i]=0; 41 vis[i]=0; 42 dis[i]=inf; 43 } 44 num=0; 45 } 46 void addedge(int fr,int to,ll cost) 47 { 48 edge[num].to=to; 49 edge[num].cost=cost; 50 edge[num].nex=head[fr]; 51 head[fr]=num++; 52 } 53 ll spfa(int st,int ed) 54 { 55 dis[st]=0; 56 vis[st]=1; 57 queue<int>q; 58 q.push(st); 59 while(!q.empty()) 60 { 61 int tmp=q.front(); 62 q.pop(); 63 vis[tmp]=0; 64 out[tmp]++; 65 if(out[tmp]>n) 66 return -1; 67 for(int i=head[tmp]; i!=-1; i=edge[i].nex) 68 { 69 int u=edge[i].to; 70 if(dis[u]>dis[tmp]+edge[i].cost) 71 { 72 dis[u]=dis[tmp]+edge[i].cost; 73 if(vis[u]) 74 continue; 75 vis[u]=1; 76 q.push(u); 77 } 78 } 79 } 80 return dis[ed]; 81 } 82 int main() 83 { 84 int T; 85 scanf("%d",&T); 86 int Case=0; 87 while(T--) 88 { 89 scanf("%d %lld",&n,&m); 90 init(); 91 for(int i=1; i<=n; i++) 92 { 93 scanf("%d",&po[i].num); 94 po[i].id=i; 95 } 96 for(int i=1; i<n; i++) 97 { 98 addedge(i+1,i,-1); 99 } 100 sort(po+1,po+n+1,cmp); 101 for(int i=1; i<n; i++) 102 { 103 int u=po[i+1].id; 104 int v=po[i].id; 105 if(u>v) 106 swap(u,v); 107 addedge(u,v,m); 108 } 109 int t1=po[1].id; 110 int t2=po[n].id; 111 if(t1>t2) 112 swap(t1,t2); 113 ll ans=spfa(t1,t2); 114 printf("Case %d: %lld\n",++Case,ans); 115 } 116 return 0; 117 } 118