二次联通门 : LibreOJ #115. 无源汇有上下界可行流
/* LibreOJ #115. 无源汇有上下界可行流 板子题 我也就会写写板子题了。。 */ #include <cstdio> #include <iostream> #include <queue> #include <cstring> const int BUF = 10000200; char Buf[BUF], *buf = Buf; void read (int &now) { for (now = 0; !isdigit (*buf); ++ buf); for (; isdigit (*buf); now = now * 10 + *buf - '0', ++ buf); } inline int min (int a, int b) { return a < b ? a : b; } #define Max 800 #define INF 1e8 int _S, _T; int low[Max << 6], _in[Max]; class Net_Flow { private : int to[Max << 6], _next[Max << 6], flow[Max << 6]; int C, list[Max << 2], deep[Max << 2], _tech[Max << 2]; int S, T; public : inline void In (int u, int v, int w) { to[++ C] = v, _next[C] = list[u], list[u] = C; to[++ C] = u, _next[C] = list[v], list[v] = C; flow[C] = 0, flow[C - 1] = w; } void Clear () { C = 1, S = _S, T = _T; } int Flowing (int now, int Flow) { if (now == T || Flow == 0) return Flow; register int res = 0, pos; for (int &i = _tech[now]; i; i = _next[i]) { if (deep[to[i]] != deep[now] + 1 || flow[i] == 0) continue; pos = Flowing (to[i], min (flow[i], Flow)); if (pos > 0) { flow[i] -= pos, res += pos, flow[i ^ 1] += pos; Flow -= pos; if (Flow <= 0) break; } } if (res != Flow) deep[now] = -1; return res; } bool Bfs () { std :: queue <int> Queue; memset (deep, -1, sizeof deep); Queue.push (S), deep[S] = 0; register int i, now; for (; !Queue.empty (); Queue.pop ()) { now = Queue.front (); for (i = list[now]; i; i = _next[i]) if (deep[to[i]] < 0 && flow[i]) { deep[to[i]] = deep[now] + 1; if (to[i] == T) return true; Queue.push (to[i]); } } return deep[T] != -1; } int Dinic () { int res = 0; for (; Bfs (); ) { for (int i = S; i <= T; ++ i) _tech[i] = list[i]; res += Flowing (S, INF); } return res; } void Print (const int &M) { printf ("YES "); for (int i = 1; i <= M; ++ i) printf ("%d ", low[i] + flow[i << 1 | 1]); } }; Net_Flow Flow; //#define Local int Main () { #ifdef Local freopen ("yukari.wife", "r", stdin); #endif fread (buf, 1, BUF, stdin); int N, M; read (N); read (M); int u, v, up; _S = 0, _T = N + 1, Flow.Clear (); for (int i = 1; i <= M; ++ i) { read (u), read (v), read (low[i]), read (up); Flow.In (u, v, up - low[i]); _in[u] -= low[i], _in[v] += low[i]; } int Total = 0; for (int i = 1; i <= N; ++ i) if (_in[i] > 0) Total += _in[i], Flow.In (_S, i, _in[i]); else if (_in[i] < 0) Flow.In (i, _T, -_in[i]); if (Flow.Dinic () != Total) return printf ("NO"), 0; else Flow.Print (M); return 0; } int ZlycerQan = Main (); int main (int argc, char *argv[]) {; }