POJ 3815 The Ninja Way(差分约束#8)

这个题同样是差分约束,求的是最矮的树和最高的树之间的最大距离,注意有一个坐标的先后关系在起作用,所以我们要想方法将数B究竟在树A左边还是右边用不同的边权表示出来,所以,B在A的左边,就从B向A连一条边(单向),C在A的右边,就从A向C连一条边,对于起点、终点两个点,最后只要求靠左边的那个点到右边的那个点的最短路就可以了。516ms

 

 

 

 

#include <cstdio>
#include <algorithm>
#include <cstdlib> 
#include <cstring>
#define N 1010 
#define M 3500
#define MAXQ  3500
using namespace std; 
const int inf = (-1u >> 1); 

int d[N], first[N];
int v[M] , w[M], next[M]; 
bool inq[N];
int cnt[N]; 
int e;
int q[MAXQ];
int indx[N]; 
int t[N]; 

void addE(int x, int y, int c)
{
      next[e] = first[x], first[x] = e;
      v[e] = y;
      w[e] = c; 
      e++;
}

bool cmp(int a, int b)
{
     return t[a] < t[b];
}
 

bool SPFA(int s, int t, int n)
{
       for (int i = 0; i < n; i++)d[i] = inf;
       memset(cnt, 0, sizeof(cnt)); 
       d[s] = 0;
       int qs, qe; 
       qs = qe = 0; 
       for (int i = 0; i < n; i++)inq[i] = false; 
       q[qe++] = s; 
       while (qs != qe)
       {
              int x = q[qs]; 
              inq[x] = false;
              for (int e = first[x]; e != -1; e = next[e])if (d[v[e]] > d[x] + w[e])
              {
                    d[v[e]] = d[x] + w[e]; 
                    if (!inq[v[e]])
                    {
                              inq[v[e]] = true;
                              q[qe++] = v[e];
                              if (qe == MAXQ)qe = 0; 
                              if (++cnt[v[e]] >= n)return false; 
                    }
              }
              qs++;
              if (qs == MAXQ)qs = 0; 
       }
       return true; 
} 

int main()
{
      int n, D;
     // FILE* fp = fopen("in.txt", "r");  
      while (scanf(  "%d %d", &n, &D) != EOF && (n + D))
      {
             e = 0; 
             for (int i = 0; i < n; i++)first[i] = -1; 
             for (int i = 0; i < n; i++) 
             { 
                  scanf( "%d", t+i);
                  indx[i] = i;
             }
             sort(indx, indx + n, cmp); 
            // for (int i = 0; i < n; i++) printf("%d ", indx[i]);puts(""); 
             int start = indx[0];
             int end = indx[n - 1];
             for (int i = 0; i < n - 1; i++)
             { 
                  int a = indx[i], b = indx[i + 1];
                  if (a < b)
                     addE(a, b, D);
                  else 
                      addE(b, a, D); 
                  addE(i + 1, i, -1);
             }
             if (start > end)start ^= end, end ^= start, start ^= end; 
             if (SPFA(start, end, n))printf("%d\n", d[end]); 
             else puts("-1");
            // getchar();getchar(); 
      }
      return 0;
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值