当最短路变成二维,就会发生非常有意思的事情。。。
问题:给出u v w,表示从u -> v(双向边)所耗的时间为w,又知道没经过一条边,获利为1(对于一天边可以来回走)。求从start到end点,获利至少为k时用的最小时间。。。
如果没有那个k,这个问题直接就是st -> ed的最短路。spfa,dijkstra。。。等等
现在可以设 dis[i][j]表示到从st到 i点经过边数为j 时的最短路。
然后直接spfa,队列中的每个点保留两个值,节点号,和到这个节点的边数。
const int N = 100010; const int M = 5024; struct node { int to; int val; int next; } g[N<<1]; class Graph { public: int head[M], t; void init() { CL(head, 0XFF); t = 0; } void add(int u, int v, int w) { g[t].to = v; g[t].val = w; g[t].next = head[u]; head[u] = t++; } } G; int dis[M][M/10]; bool vis[M][M/10]; int n, k; struct pnode { int v; int c; pnode() {} pnode(int a, int b) : v(a), c(b) {} }; int solve(int st, int ed) { queue<pnode> q; pnode u; int v, i, j, sum; for(i = 0; i <= n; ++i) { for(j = 0; j <= k; ++j) { dis[i][j] = inf; vis[i][j] = false; } } vis[st][0] = true; dis[st][0] = 0; q.push(pnode(st, 0)); while(!q.empty()) { u = q.front(); q.pop(); vis[u.v][u.c] = false; for(i = G.head[u.v]; i != -1; i = g[i].next) { sum = u.c + 10; if(sum > k) sum = k; // 边数 > k时可以直接压缩到k。 v = g[i].to; if(dis[v][sum] > dis[u.v][u.c] + g[i].val) { dis[v][sum] = dis[u.v][u.c] + g[i].val; if(!vis[v][sum]) { vis[v][sum] = true; q.push(pnode(v, sum)); } } } } return dis[ed][k]; }