差分约束第一题,差分约束就是解一系列的形如x1-x2<=(>=)a的不等式,由于移项之后为x1<=(>=)x2+a和最短路径的dist[i] <(>) dist[u] + mapp[u][i]联系 起来,故可以用最短路bellmanford和SPFA求解
显然dist[i]和dist[u]都为方程的解,根据大于或者小于可以以最短路径或者最长路径求解
我们举最短路径为例
因为是求的最短路径,那么结果可以保证dist[i] <= dist[u]+mapp[u][i],那么对此不等式移向可以得到dist[i] - dist[u] <= mapp[u][i],在最短路中,i,u分别为两个节点,而且存在一条u->i的路径。
现在回到POJ1201,输入样例如下:
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
设第i个点以前被选中的数有Si个,那么对于输入的一段闭区间[a, b]中有c[i]个数被选中,就有以下不等式方程:
(1)Sb[i] - Sa[i] >= c[i];
(2)1 >= Si-S(i-1) >= 0;
由于我们是以最短路径为例,故将上述不等式改为
(1)Sa[i] - Sb[i] <= -1*c[i];
(2)Si - S(i-1) <= 1;
(3)S(i-1) - S(i) <= 0;
据上述差分约束方程求解可以建图,对第一个输入,可以建图7->2,权值为-3,这样依次将全部输入建图,但是因为最后的结果可能是一个非连通图,所以还要根据上述不等式对每一个[i, i+1]建图,建图完后一次SPFA就可以求解
注意:最终答案是-dist[minn-1],最长路径则为dist[maxx+1];
附AC代码:
(最短路径)
#include <iostream> #include <vector> #include <queue> using namespace std; struct node { int num; int value; }; const int size = 51000; bool inque[size]; int dist[size]; vector <node> mapp[size]; int minn, maxx; void init() { for (int i = 0; i < size; i ++){ mapp[i].clear(); } } void SPFA(int s1) { queue <node> que; for (int i = minn; i <= maxx; i ++){ inque[i] = false; dist[i] = 100000000; } node s; s.num = s1; s.value = 0; que.push(s); dist[s.num] = 0; inque[s.num] = true; while (!que.empty()){ node e = que.front(); inque[e.num] = false; que.pop(); for (int i = 0; i < mapp[e.num].size(); i ++){ node ee = mapp[e.num][i]; if (dist[ee.num] > dist[e.num] + ee.value){ dist[ee.num] = dist[e.num] + ee.value; if (!inque[ee.num]){ ee.value = dist[ee.num]; que.push(ee); inque[ee.num] = true; } } } } } int main() { int n; while (scanf("%d", &n) != EOF){ init(); node a, b; minn = INT_MAX, maxx = -1; for (int i = 0; i < n; i ++){ scanf("%d%d%d", &a.num, &b.num, &a.value); minn = minn > a.num? a.num : minn; maxx = maxx < b.num? b.num : maxx; a.num --; a.value*=-1; mapp[b.num].push_back(a); } for (int i = minn; i <= maxx; i ++){ a.num = i, a.value = 0; mapp[i+1].push_back(a); a.num = i+1, a.value = 1; mapp[i].push_back(a); } SPFA(maxx); printf("%d\n", -dist[minn-1]); } return 0; } /*(最长路径)*/ #include <iostream> #include <vector> #include <queue> using namespace std; struct node { int num; int value; }; const int size = 51000; bool inque[size]; int dist[size]; vector <node> mapp[size]; int minn, maxx; void init() { for (int i = 0; i < size; i ++){ mapp[i].clear(); } } void SPFA(int n, int s1) { queue <node> que; for (int i = minn; i <= maxx; i ++){ inque[i] = false; dist[i] = -100000000; } node s; s.num = s1; s.value = 0; que.push(s); dist[s.num] = 0; inque[s.num] = true; while (!que.empty()){ node e = que.front(); inque[e.num] = false; que.pop(); for (int i = 0; i < mapp[e.num].size(); i ++){ node ee = mapp[e.num][i]; if (dist[ee.num] < dist[e.num] + ee.value){ dist[ee.num] = dist[e.num] + ee.value; if (!inque[ee.num]){ ee.value = dist[ee.num]; que.push(ee); inque[ee.num] = true; } } } } } int main() { int n; while (scanf("%d", &n) != EOF){ init(); node a, b; minn = INT_MAX, maxx = -1; for (int i = 0; i < n; i ++){ scanf("%d%d%d", &a.num, &b.num, &b.value); minn = minn > a.num? a.num : minn; maxx = maxx < b.num? b.num : maxx; b.num ++; mapp[a.num].push_back(b); } for (int i = minn; i <= maxx; i ++){ a.num = i+1, a.value = 0; mapp[i].push_back(a); a.num = i, a.value = -1; mapp[i+1].push_back(a); } SPFA(maxx, minn); printf("%d\n", dist[maxx+1]); } return 0; }