將已知條件抽象:
d[i+1] + 0 >= d[i]
d[AL]+DL >= d[BL]
d[BD]+(-DD) >= d[AD]
問題爲:
滿足以上諸多條件的情況下,求出d[n] – d[1]的最大值。
即求d[1]+ MAX>=d[n] 中MAX的值。
分析:
1)d[i]+x >= d[j] d[k]+y>= d[i] 則有d[k]+(x+y)>=d[i]
符合遞推特性
2)d[m]+x>=d[n]
如若d[n]可由多個d[m]{m屬於1到N}轉移得到,又由於各個方程需要同時滿足,故取各個d[n]中的最小值
以上分析可得
d[n] = min{d[m] + x爲兩者差}
具體思路:
將方程以圖論模型中的邊表示
struct link
{
int from;
int to;
int cost;
}; // from + cost >= to
轉化爲最短路問題求解
算法主體思想:
不斷由邊更新每個點的值,如有解則可在 點數*邊數時間,即O(N*(N+ML+MD))內完成所有點值的更新。
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define INF 1e9
using namespace std;
struct LL
{
int from;
int to;
int cost;
}; // d[from] + cost >= d[to]
LL link[20010];
int d[1010];
int main()
{
int num_node, num_link1, num_link2;
scanf("%d %d %d", &num_node, &num_link1, &num_link2);
fill(d, d + num_node, INF);
d[0] = 0;
// preparing for graph
for (int i = 0; i < num_link1; ++i)
{
int AL, BL, DL; // d[AL] + DL >= d[BL]
scanf("%d %d %d", &AL, &BL, &DL);
link[i].from = AL-1;
link[i].to = BL-1;
link[i].cost = DL;
}
for (int i = num_link1; i < num_link1 + num_link2; ++i)
{
int AD, BD, DD; // d[BD] + (-DD) >= d[AD]
scanf("%d %d %d", &AD, &BD, &DD);
link[i].from = BD-1;
link[i].to = AD-1;
link[i].cost = -DD;
}
for (int i = 0; i < num_node; ++i)
{
for (int j = 0; j+1 < num_node; ++j)
if(d[j+1]<INF)
d[j] = min(d[j], d[j+1]);
for (int j = 0; j < num_link1+num_link2; ++j)
if(d[link[j].from]<INF)
d[link[j].to] = min(d[link[j].to], d[link[j].from]+link[j].cost);
}
int res = d[num_node-1];
if(d[0] < 0)
res = -1;
else if(res == INF)
res = -2;
printf("%d\n", res);
}