poj 1062

有条件的最短路径算法,穷举可行的等级即可。

  1 #include <iostream>
  2 #include <string>
  3 #include <vector>
  4 #include <cstdlib>
  5 #include <cmath>
  6 #include <map>
  7 #include <algorithm>
  8 #include <list>
  9 #include <ctime>
 10 #include <set>
 11 #include <string.h>
 12 #include <queue>
 13 #include <cstdio>
 14 using namespace std;
 15 typedef int typep;
 16 int maxData = 500000;
 17 #define N 505
 18 #define CLR(arr, what) memset(arr, what, sizeof(arr))
 19 int path[N][N];
 20 int d[N];
 21 int n;
 22 //double maxData = 0;
 23 int lvl, lvr;
 24 int costc[N];
 25 int costlv[N];
 26 
 27 bool check(int lv) {
 28     return (lvl <= lv && lv <= lvr);
 29 }
 30 
 31 bool relax(typep u, typep& v, typep w, typep lv1, typep lv2) {
 32     if (v > (u + w) && check(lv1) && check(lv2)) {
 33         v = u + w;
 34         return true;
 35     } else
 36         return false;
 37 }
 38 
 39 int cnt[N]; //记录顶点入队列次数
 40 bool final[N]; //记录顶点是否在队列中,SPFA算法可以入队列多次
 41 bool SPFA(int s) {
 42     queue<int> myqueue;
 43     int i;
 44     CLR(final, 0);
 45     CLR(cnt, 0);
 46     final[s] = true;
 47     cnt[s]++; //源点的入队列次数增加
 48     myqueue.push(s);
 49     int topint;
 50     bool judge;
 51     while (!myqueue.empty()) {
 52         topint = myqueue.front();
 53         myqueue.pop();
 54         final[topint] = false;
 55         for (i = 0; i < n; ++i) {
 56             if (d[topint] < maxData) {
 57                 judge = relax(d[topint], d[i], path[topint][i], costlv[topint], costlv[i]);
 58                 if (judge) {
 59                     if (!final[i]) { //判断是否在当前的队列中
 60                         final[i] = true;
 61                         cnt[i]++;
 62                         if (cnt[i] >= n) //当一个点入队的次数>=n时就证明出现了负环。
 63                             return true;
 64                         myqueue.push(i);
 65                     }
 66                 }
 67             }
 68         }
 69     }
 70     return false;
 71 }
 72 
 73 
 74 int main() {
 75     int degree, num, cp, cl, cx, rpob, rpmo;
 76     cin >> degree >> num;
 77     n = num;
 78     bool judge;
 79     CLR(path, maxData);
 80     for (int abc = 0; abc < num; abc++) {
 81         scanf("%d%d%d", &cp, &cl, &cx);
 82         costc[abc] = cp;
 83         costlv[abc] = cl;
 84         for (int i = 0; i < cx; i++) {
 85             scanf("%d%d", &rpob, &rpmo);
 86             rpob--;
 87             path[abc][rpob] = rpmo;
 88         }
 89     }
 90     int res = maxData;
 91     for (int i = costlv[0] - degree; i < costlv[0] + 1; i++) {
 92         lvl = i;
 93         lvr = i + degree;
 94         CLR(d, maxData);
 95         d[0] = 0;
 96         judge = SPFA(0);
 97         for (int i = 0; i < n; i++) {
 98             res = min(res, d[i] + costc[i]);
 99         }
100     }
101     cout << res;
102     return 0;
103 }

邻接表的依旧更快一些

  1 #include <iostream>
  2 #include <string>
  3 #include <vector>
  4 #include <cstdlib>
  5 #include <cmath>
  6 #include <map>
  7 #include <algorithm>
  8 #include <list>
  9 #include <ctime>
 10 #include <set>
 11 #include <string.h>
 12 #include <queue>
 13 #include <cstdio>
 14 using namespace std;
 15 typedef int typep;
 16 #define N 505
 17 #define CLR(arr, what) memset(arr, what, sizeof(arr))
 18 //double maxData = 0;
 19 int lvl, lvr;
 20 int costc[N];
 21 int costlv[N];
 22 
 23 bool check(int lv) {
 24     return (lvl <= lv && lv <= lvr);
 25 }
 26 
 27 bool relax(typep u, typep& v, typep w, typep lv1, typep lv2) {
 28     if (v > (u + w) && check(lv1) && check(lv2)) {
 29         v = u + w;
 30         return true;
 31     } else
 32         return false;
 33 }
 34 
 35 typedef int typep;
 36 const int E = 10000;
 37 const int V = 100;
 38 #define typec int                       // type of cost
 39 const typec inf = 10000000; // max of cost
 40 int n, m, pre[V], edge[E][3];
 41 typec dist[V];
 42 int bellman(int src) {
 43     int i, j;
 44     for (i = 0; i < n; ++i) {
 45         dist[i] = inf;
 46         pre[i] = -1;
 47     }
 48     dist[src] = 0;
 49     bool flag;
 50     for (i = 1; i < n; ++i) {
 51         flag = false; //  优化
 52         for (j = 0; j < m; ++j) {
 53             if (1
 54                     == relax(dist[edge[j][0]], dist[edge[j][1]], edge[j][2],
 55                             costlv[edge[j][0]], costlv[edge[j][1]]))
 56                 flag = true;
 57         }
 58         if (!flag)
 59             break;
 60     }
 61     for (j = 0; j < m; ++j) {
 62         if (1
 63                 == relax(dist[edge[j][0]], dist[edge[j][1]], edge[j][2],
 64                         costlv[edge[j][0]], costlv[edge[j][1]]))
 65             return 0; //  有负圈
 66     }
 67     return 1;
 68 }
 69 inline void addedge(int u, int v, typec c) {
 70     edge[m][0] = u;
 71     edge[m][1] = v;
 72     edge[m][2] = c;
 73     m++;
 74 }
 75 
 76 int main() {
 77     int degree, num, cp, cl, cx, rpob, rpmo;
 78     cin >> degree >> num;
 79     n = num;
 80     bool judge;
 81     for (int abc = 0; abc < num; abc++) {
 82         scanf("%d%d%d", &cp, &cl, &cx);
 83         costc[abc] = cp;
 84         costlv[abc] = cl;
 85         for (int i = 0; i < cx; i++) {
 86             scanf("%d%d", &rpob, &rpmo);
 87             rpob--;
 88             addedge(abc, rpob, rpmo);
 89         }
 90     }
 91     int res = inf;
 92     for (int i = costlv[0] - degree; i < costlv[0] + 1; i++) {
 93         lvl = i;
 94         lvr = i + degree;
 95         judge = bellman(0);
 96         for (int i = 0; i < n; i++) {
 97             res = min(res, dist[i] + costc[i]);
 98         }
 99     }
100     cout << res;
101     return 0;
102 }

from kakamilan

原文地址:https://www.cnblogs.com/kakamilan/p/3079690.html