poj 1364 King (差分約束系統)

來源:互聯網
上載者:User

    在找圖的相關題目時找到這道題,看了半天沒有發現和圖有哪門子關係,看discuss裡面才瞭解到這個叫做“差分約束系統”的東東。趕緊百度一下,學習學習。糾結了我幾天,受益匪淺。花了我30多個 submit來測試。才搞懂了。。。

 

   題目大意:已知一個序列 s[1...n],給出它的 m個子序列以及對該子序列的約束條件,例如 s[a],s[a+1],s[a+2],...,s[a+b];且s[a]+s[a+1]+s[a+2]+...+s[a+b] < or > k。問題關鍵在於如何轉化約束條件,用前n項和來轉化成兩兩之間的關係。如:s[a]+s[a+1]+...+s[a+b] < k 可以轉化成前n項和 sum[a+b]-sum[a-1] < k,為了能用Bellman_Ford,即將'<'轉化成'<=',可以寫成sum[a+b]-sum[a-1] <= k-1.若是 s[a]+s[a+1]+...+s[a+b] > k 可轉化成 sum[a+b]-sum[a-1] >= k+1, 即 sum[a-1]-sum[a+b] <= -k-1;

Bellman-Ford演算法實現:

#include <stdio.h>  #define INF 100000000  struct  {      int s, e, v;  } edge[105];  int n, nedge;  int dis[105];  void add(int s, int e, int v)  {      edge[nedge].s = s;      edge[nedge].e = e;      edge[nedge].v = v;      nedge++;  }  int relax(int s, int e, int v)  {      if (dis[s]+v < dis[e])      {          dis[e] = dis[s]+v;          return 1;      }      return 0;  }  int BellmanFord(int s0)  {      int i, j;      //Initialize      for (i=0; i<=n; i++)          dis[i] = INF;      dis[s0] = 0;      //Relax      for (i=1; i<=n; i++) //引入一個源點0之後就有n+1個頂點了          for (j=0; j<nedge; j++)              relax(edge[j].s, edge[j].e, edge[j].v);      //Check Negative power circuit      for (i=0; i<nedge; i++)          if (relax(edge[i].s, edge[i].e, edge[i].v))              return 1;      return 0;  }  int main()  {      int  m, a, b, k;      char c[4];      while (scanf("%d", &n) && n)      {          scanf("%d", &m);          nedge = 0;          while (m--)          {              scanf("%d %d %s %d", &a, &b, c, &k);              if (c[0] == 'l')                  add(a-1, a+b, k-1);              else                  add(a+b, a-1, -k-1);          }          if (BellmanFord(0))              printf("successful conspiracy/n");          else              printf("lamentable kingdom/n");      }      return 0;  }

SPFA演算法實現:

#include <stdio.h>  #include <string.h>  #include <stdlib.h>  #define INF 100000000  struct EDGE  {      int nd;  //終點      int eg;  //邊權      struct EDGE *nxt;  };  struct  {      struct EDGE *head, *last;  } node[120];  /*  鄰接表格儲存體 */  int n;  int dis[120];  int Q[20000], vst[120], cnt[120];  void add(int s, int e, int v)  {      struct EDGE *p;      p = (struct EDGE*)malloc(sizeof(struct EDGE));      p->nd = e;      p->eg = v;      p->nxt = NULL;      if (node[s].head == NULL)      {          node[s].head = p;          node[s].last = p;      }      else      {          node[s].last->nxt = p;          node[s].last = p;      }  }  int relax(int s, int e, int v)  {      if (dis[s]+v < dis[e])      {          dis[e] = dis[s]+v;          return 1;      }      return 0;  }  /*  隊列實現SPFA  */  int SPFA(int s0)  {      int i, p, q;      struct EDGE *pp;      memset(vst, 0, sizeof(vst));      memset(cnt, 0, sizeof(cnt));      for (i=0; i<=n+1; i++)          dis[i] = INF;      dis[s0] = 0;      Q[0] = s0; p = 0; q = 1;      vst[s0] = 1;      cnt[s0]++;      while (p < q)      {          pp = node[Q[p]].head;          while (pp)          {              if (relax(Q[p], pp->nd, pp->eg) && !vst[pp->nd])              {                  Q[q++] = pp->nd;                  vst[pp->nd] = 1;                  cnt[pp->nd]++;                  if (cnt[pp->nd] > n+1)                      return 1;              }              pp = pp->nxt;          }          vst[Q[p]] = 0;          p++;      }      return 0;  }  int main()  {      int  m, a, b, k;      char c[4];      while (scanf("%d", &n) && n)      {          memset(node, 0, sizeof(node));          scanf("%d", &m);          while (m--)          {              scanf("%d %d %s %d", &a, &b, c, &k);              if (c[0] == 'l')                  add(a-1, a+b, k-1);              else                  add(a+b, a-1, -k-1);          }          //附加n+1點當做源點          for (k=0; k<=n; k++)              add(n+1, k, 0);          if (SPFA(n+1))              printf("successful conspiracy/n");          else              printf("lamentable kingdom/n");      }      return 0;  }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.