洛谷P4043 支线剧情
题意:给定DAG,通过每条边需要时间。
从某号点回到1号点不需要时间。
从1号点出发,求最少要多久才能走完所有边。
解:
有源汇有上下界最小费用可行流。
直接连边,费用为时间,下界为1,无上界。
每个点都可能是终点,往t连边。
1 #include <cstdio> 2 #include <algorithm> 3 #include <queue> 4 #include <cstring> 5 6 const int N = 310, M = 1000010, INF = 0x3f3f3f3f; 7 8 struct Edge { 9 int nex, v, c, len; 10 }edge[M << 1]; int top = 1; 11 12 int e[N], d[N], vis[N], pre[N], flow[N], ot[N]; 13 std::queue<int> Q; 14 15 inline void add(int x, int y, int z, int w) { 16 top++; 17 edge[top].v = y; 18 edge[top].c = z; 19 edge[top].len = w; 20 edge[top].nex = e[x]; 21 e[x] = top; 22 23 top++; 24 edge[top].v = x; 25 edge[top].c = 0; 26 edge[top].len = -w; 27 edge[top].nex = e[y]; 28 e[y] = top; 29 return; 30 } 31 32 inline bool SPFA(int s, int t) { 33 memset(d, 0x3f, sizeof(d)); 34 d[s] = 0; 35 flow[s] = INF; 36 vis[s] = 1; 37 Q.push(s); 38 while(!Q.empty()) { 39 int x = Q.front(); 40 Q.pop(); 41 vis[x] = 0; 42 for(int i = e[x]; i; i = edge[i].nex) { 43 int y = edge[i].v; 44 if(edge[i].c && d[y] > d[x] + edge[i].len) { 45 d[y] = d[x] + edge[i].len; 46 pre[y] = i; 47 flow[y] = std::min(flow[x], edge[i].c); 48 if(!vis[y]) { 49 vis[y] = 1; 50 Q.push(y); 51 } 52 } 53 } 54 } 55 return d[t] < INF; 56 } 57 58 inline void update(int s, int t) { 59 int temp = flow[t]; 60 while(t != s) { 61 int i = pre[t]; 62 edge[i].c -= temp; 63 edge[i ^ 1].c += temp; 64 t = edge[i ^ 1].v; 65 } 66 return; 67 } 68 69 inline int solve(int s, int t, int &cost) { 70 int ans = 0; 71 cost = 0; 72 while(SPFA(s, t)) { 73 ans += flow[t]; 74 cost += flow[t] * d[t]; 75 update(s, t); 76 } 77 return ans; 78 } 79 80 int main() { 81 int n, cost = 0; 82 scanf("%d", &n); 83 int ss = n + 1, tt = n + 2, t = n + 3; 84 for(int i = 1, x, y, z; i <= n; i++) { 85 scanf("%d", &x); 86 for(int j = 1; j <= x; j++) { 87 scanf("%d%d", &y, &z); 88 // i -> y z 89 add(i, y, INF, z); 90 ot[i]++; 91 ot[y]--; 92 cost += z; 93 } 94 add(i, t, INF, 0); 95 } 96 for(int i = 1; i <= n; i++) { 97 if(ot[i] > 0) { 98 add(i, tt, ot[i], 0); 99 } 100 else { 101 add(ss, i, -ot[i], 0); 102 } 103 } 104 add(t, 1, INF, 0); 105 int ans; 106 solve(ss, tt, ans); 107 printf("%d", ans + cost); 108 return 0; 109 }