HDU--3440(差分约束)
2015-01-10 15:06:21
思路:很好的一道差分约束题,拥有灵活的建图。
由于题目求的是从起点(最矮的房子)到终点(最高的房子)的有向距离最大值,那么在建图以及跑最短路时要特别注意方向。
首先按照房子的读入顺序给房子编号为1~N,用结构体记录下房子的高度、编号,然后按照高度升序排序。
这样排完序后自然就是从第1个房子一直跳到第N个房子。
约束条件:排序前:pos[i] - pos[i - 1] >= 1
排序后:比较一下id[i] , id[i - 1]的大小(用id[i]来记录排序后第i个房子在输入中的位置)
(1)如果id[i] > id[i - 1]说明从排序后第i-1个房子跳到第i个房子要往后跳 pos[id[i]] - pos[id[i - 1]] >= D
(2)如果id[i] < id[i - 1]说明从排序后第i-1个房子跳到第i个房子要往前跳 pos[id[i - 1]] - pos[id[i]] >= D
最后,要判断下id[1]和id[N]的大小,选取小的为起点,大的为终点来跑最短路,这样答案才为正。(我就被坑在这好久。。。)
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <iostream> 11 #include <algorithm> 12 using namespace std; 13 #define lp (p << 1) 14 #define rp (p << 1|1) 15 #define getmid(l,r) (l + (r - l) / 2) 16 #define MP(a,b) make_pair(a,b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 typedef pair<int,int> pii; 20 const int INF = (1 << 30) - 1; 21 const int maxn = 1010; 22 23 int T,N,D; 24 int first[maxn],ecnt; 25 int inq[maxn],cnt[maxn],dis[maxn]; 26 27 struct edge{ 28 int u,v,next,cost; 29 }e[maxn << 1]; 30 31 struct node{ 32 int h,id; 33 }t[maxn]; 34 35 bool cmp(node a,node b){ 36 return a.h < b.h; 37 } 38 39 void Add_edge(int u,int v,int c){ 40 e[++ecnt].next = first[u]; 41 e[ecnt].u = u; 42 e[ecnt].v = v; 43 e[ecnt].cost = c; 44 first[u] = ecnt; 45 } 46 47 bool Spfa(int s){ 48 queue<int> Q; 49 memset(inq,0,sizeof(inq)); 50 memset(cnt,0,sizeof(cnt)); 51 fill(dis + 1,dis + N + 1,INF); 52 dis[s] = 0; 53 cnt[s] = 1; 54 Q.push(s); 55 while(!Q.empty()){ 56 int x = Q.front(); Q.pop(); 57 inq[x] = 0; 58 for(int i = first[x]; ~i; i = e[i].next){ 59 int v = e[i].v; 60 if(dis[v] > dis[x] + e[i].cost){ 61 dis[v] = dis[x] + e[i].cost; 62 if(inq[v] == 0){ 63 inq[v] = 1; 64 if(++cnt[v] > N) return false; 65 Q.push(v); 66 } 67 } 68 } 69 } 70 return true; 71 } 72 73 int main(){ 74 scanf("%d",&T); 75 for(int tt = 1; tt <= T; ++tt){ 76 memset(first,-1,sizeof(first)); 77 ecnt = 0; 78 scanf("%d%d",&N,&D); 79 for(int i = 1; i <= N; ++i){ 80 scanf("%d",&t[i].h); 81 t[i].id = i; 82 //pos[i] - pos[i - 1] >= 1 --> pos[i - 1] <= pos[i] - 1 83 Add_edge(i,i - 1,-1); 84 } 85 sort(t + 1,t + N + 1,cmp); 86 for(int i = 2; i <= N; ++i){ 87 if(t[i].id > t[i - 1].id){ 88 //pos[t[i].id] - pos[t[i - 1].id] <= D 89 //pos[t[i].id] <= pos[t[i - 1].id] + D 90 Add_edge(t[i - 1].id,t[i].id,D); 91 } 92 else{ 93 //pos[t[i - 1].id] - pos[t[i].id] <= D 94 //pos[t[i - 1].id] <= pos[t[i].id] + D 95 Add_edge(t[i].id,t[i - 1].id,D); 96 } 97 } 98 printf("Case %d: ",tt); 99 int st = min(t[1].id,t[N].id); 100 int ed = t[1].id + t[N].id - st; 101 if(Spfa(st)) printf("%d\n",dis[ed]); 102 else printf("-1\n"); 103 } 104 return 0; 105 }