Delay Constrained Maximum Capacity Path
带限制的最短路。二分最小最大容量c,然后用dijkstra(优先队列优化)做最短路,在做最短路的时候,保证边的容量cap(i, j)>=c。时间复杂度为O(nlogn * log(max(c)))。当然在做最短路的时候是可以优化的,有以下几种优化办法:
1.时间优化,如果当前队列中弹出的点的时间(因为算的是从起点到该点的最短时间)超过时间限制,就不用搜了。
2.如果当前已经计算到了目标点(N),那么就可以不用再继续向下搜了。
最后需要注意的就是数据范围,由于多次因为对于比较大的数据处理失误,所以表示对于2*10^9,还是处理成long long最为妥当。
#include <stdio.h> #include <string.h> #include <queue> using namespace std; const int Vertex = 10500; const int Edge = 50500; const int INF = 0x3f3f3f3f; typedef long long LL; struct Pair{ int v, t; Pair(int iv, int it): v(iv), t(it){} bool operator<(const Pair&a)const{ return t > a.t; } }; int d[Vertex], f[Vertex], e[Edge*2], to[Edge*2], tim[Edge*2]; LL cap[Edge*2]; bool vis[Vertex]; int N, M, T, tot; void add(int v, int u, LL c, int t){ e[tot] = f[v]; to[tot] = u, cap[tot] = c, tim[tot] = t; f[v] = tot ++; } inline LL max(LL x, LL y){ return x > y ? x : y; } bool bfs(int src, LL lim){ //printf(">> %I64d\n", lim); memset(vis, 0, sizeof(vis)); memset(d, 0x3f, sizeof(d)); d[src] = 0; priority_queue<Pair> Q; Q.push(Pair(src, 0)); while(!Q.empty()){ Pair cur = Q.top(); Q.pop(); //printf(">>v = %d\n", cur.v); if(cur.t > T) break; if(vis[N]) break; if(vis[cur.v]) continue; vis[cur.v] = 1; for(int i = f[cur.v]; i!=-1; i = e[i]){ int u = to[i]; if(cap[i] < lim) continue; if(!vis[u] && d[u] > cur.t + tim[i]){ d[u] = cur.t + tim[i]; Q.push(Pair(u, d[u])); } } } return vis[N] && d[N] <= T; } int main(){ int tcase; LL l, r; freopen("test.in", "r", stdin); scanf("%d", &tcase); while(tcase--){ scanf("%d%d%d", &N, &M, &T); tot = 0; memset(f, -1, sizeof(f)); l = r = 0; for(int i = 0; i < M; i ++){ int x, y, t; LL c; scanf("%d%d%I64d%d", &x, &y, &c, &t); add(x, y, c, t); add(y, x, c, t); r = max(r, c); } while(l <= r){ LL mid = (l+r)/2; if(bfs(1, mid)) l = mid + 1; else r = mid - 1; } printf("%I64d\n", r); } return 0; }