听着名字挺高大上的,其实就是形如下列不等式的集合 C-A <= k ,那么为什么取这个名字:“差分”:因为左边是两个变量的差,“约束”:这个式子有 <= k 这个限制条件。
然后着眼解决方案,通过观察可以得到,它和最短路的松弛操作很像:当 dis[v] > dis[u] + w[u,v] 时松弛,即算法正常执行结束后,dis[v] - dis[u]<= w[u,v] 恒成立,于是就可以转换成求最短路的问题。
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; const int inf = 0x3f3f3f3f; const int N = 30100; const int M = 160000; int tot; struct Edge{ int v, cost, next; }edge[M]; struct qnode{ int v, c; bool operator < (const qnode &x) const { return c > x. c; } }; int head[M]; bool vis[N]; int dis[N]; void addedge(int u, int v, int w){ edge[tot]. v = v; edge[tot]. cost = w; edge[tot]. next = head[u]; head[u] = tot ++; } void dijkstra(){ memset(vis, false, sizeof(vis)); memset(dis, 0x3f, sizeof(dis)); dis[1] = 0; priority_queue <qnode> q; q. push({1, 0}); while(! q. empty()){ qnode t = q. top(); q. pop(); if(vis[t. v]) continue; vis[t. v] = true; for(int i = head[t. v]; i != -1; i = edge[i]. next){ int v = edge[i]. v; int cost = edge[i]. cost; if(! vis[v] && dis[v] > dis[t. v] + cost){ dis[v] = dis[t. v] + cost; q. push({v, dis[v]}); } } } } int main(){ int n, m; while(~ scanf("%d%d", &n, &m)){ int a, b, c; tot = 1; memset(head, -1, sizeof(head)); while(m --){ scanf("%d%d%d", &a, &b, &c); addedge(a, b, c); } dijkstra(); printf("%d\n", dis[n]); } return 0; }