Portal:
pid=4888 ">" HDU "4888 Redraw Beautiful drawings
Topic Analysis:
The game saw a network flow, but did not knock out. A variety of negative examples to tear themselves down (the reason is not willing to write violence inference).
The first is a simple row to build the edge. The source point builds edges to the row. The capacity is the line element and, the sink point, and the Lie Jian edge. The capacity is for the column element and. All rows to all Lie Jian edges, with a capacity of K.
Run the maximum flow one time. Marue have the solution, otherwise there is no solution.
The next step is to infer whether the solution is unique.
The puzzle is not understood at all. Or a violent dafa good.
The simplest idea is to enumerate the four ends of a rectangle. Set the endpoint on the main diagonal of a and d. B, C is the endpoint on the vice-diagonal. Only A, d is not equal to K and B, C is not equal to 0, then there is solution.
The corresponding only to B, C is not equal to K and a, d is not equal to 0, then the same solution.
So. Enumerating all of the rectangle complexity up to O (n^4), too large, we need to reduce the complexity.
So how do we reduce the complexity?
Now we set up a two-dimensional array can[I [j] means that there is a row in the line before the current row that satisfies the element of column I is not equal to 0 and the element of column J is not equal to K, then can[I [j] = 1, assuming that the bank also satisfies column I is not equal to K and column J is not equal to That means there are multiple solutions. Otherwise the can[J [i] is marked as 1. Then proceed with the scan.
The above procedure infers the output solution after the unique solution. (I, j) The corresponding element is the flow of the opposite edge of row I to column J.
The code is as follows:
#include <cstdio> #include <cstring> #include <algorithm>using namespace std; #define REP (I, A, b) for (int i = A; I < b; + + i) #define for (I, A, b) for (int i = A; I <= B; + + i) #define REV (I, A, b) for (int i = a-1; I >= b;--i) #define FOV (I, A, b) for (int i = A; I >= b;--i) #define CLR (A, x) MEMS ET (A, X, sizeof a) #define CPY (A, X) memcpy (A, x, sizeof a) const int MAXM = 405; Const int MAXN = 1005; const int MAXQ = 500000; const int maxe = 500000; const int INF = 0x3f3f3f3f; struct Edge {int V, c, N; Edge () {}edge (int v, int c, int n): V (v), C (c), n (n) {}}, struct NetWork {Edge e[maxe]; int H[MAXN], cn TE; int D[MAXN], CUR[MAXN], NUM[MAXN], PRE[MAXN]; int Q[MAXQ], head, tail; int n, m, k; int s, T, NV; int flow; I NT ROW[MAXN], COL[MAXN]; int G[MAXM][MAXM]; int CAN[MAXM][MAXM]; void init () {cnte = 0; CLR (H,-1);} void Addedge (int u, int v, int c) {E[cnte] = Edge (V,C, H[u]); H[u] = Cnte + +; E[cnte] = Edge (u, 0, h[v]); H[V] = Cnte + +;} void Rev_bfs () {CLR (d,-1); CLR (num, 0); head = tail = 0; Q[tail + +] = t;d [t] = 0; num[d[t]] = 1; while (head! = tail) {int u = q[head + +]; for (int i = h[u]; ~i; i = E[I].N {int v = e[i].v, if (~d[v]) continue;d [v] = D[u] + 1; num[d[v]] + +; Q[tail + +] = V;}}} int Isap () {CPY (cur, H); Rev_bfs (); flow = 0; int u = pre[s] = s, i; while (D[s] < NV) {if (U = = t) {int f = INF, POS; for (i = s; I! = t; i = E[CUR[I]].V) if (F > e[cur[i]].c) {f = e[cur[i]].c;p os = i;} for (i = s; I! = t; i = E[CUR[I]].V) {e[cur[i]].c-= f; E[cur[i] ^ 1].c + = f; Flow + = f; u = pos;} for (i = cur[u]; ~i, i = E[I].N) if (e[i].c && d[u] = = D[E[I].V] + 1) break; if (~i) {Cur[u] = i;p re[e[i].v ] = u; u = e[i].v;} else {if (0 = = (--num[d[u]])) break, int mmin = NV, for (i = h[u]; ~i; i = E[I].N) if (e[i].c && mmin > D[E[I].V]) {Cur[u] = i; mmin = d[e[i].v];} D[U] = mmin + 1; num[d[u]] + +; u = Pre[u];}} return flow;} void put () {printf ("unique\n"); For (i, 1, N) for (j, 1, m) printf ("%d%c", G[i][j], J < m? ': ' \ n ');} void Build () {for (U, 1, n) for (int i = h[u]; ~i; i = E[I].N) if (E[I].V) g[u][e[i].v-n] = e[i ^ 1].c;} int check () {CLR (can, 0); For (R, 1, N) for (I, 1, M) for (J, i + 1, m) {int tmp1 = 0, tmp2 = 0; if (g[r][i]! = k && G[r][j]! = 0) {if (Can[i][j]) return 1; tmp1 = 1;} if (g[r][i]! = 0 && g[r][j]! = k) {if (Can[j][i]) return 1; tmp2 = 1;} if (TMP1) can[j][i] = TMP1; if (TMP2) can[i][j] = TMP2;} return 0;} void Solve () {int sum1 = 0; int sum2 = 0; init (); s = 0; t = n + m + 1; NV = t + 1; For (i, 1, n) {scanf ("%d", &row[i]), Addedge (S, I, Row[i]); SUM1 + = Row[i];} For (I, 1, m) {scanf ("%d", &col[i]), Addedge (i + N, T, Col[i]); sum2 + = Col[i];} For (i, 1, N) for (j, 1, m) Addedge (i, n + j, k); Isap (); if (floW! = Sum1 | | Flow! = sum2) {printf ("impossible\n"); return;} Build (); int multi = Check (), if (multi) printf ("Not unique\n"); Elseput ();}} NW; int main () {while (~scanf ("%d%d%d", &NW.N, &NW.M, &NW.K)) nw.solve (); return 0;}
The solution is still not understood, but the Dfs method will be. The thought is similar to the above, looking for the ring with the thought of backtracking. It is known that a ring of length equal to 2 is not feasible (since both points are self) and must be a ring with a length greater than or equal to 4 (which can form a ring with an even length). We only want to backtrack on each line, assuming that the flow capacity along the rows to the column can be reduced (the elements that belong to the larger) or column to row and capacity can be reduced (rows to columns and capacity can be added, belonging to the elements can be smaller) to find the ring on the side to explain the multi-solution.
The code is as follows:
#include <cstdio> #include <cstring> #include <algorithm>using namespace std; #define REP (I, A, b) for (int i = A; I < b; + + i) #define for (I, A, b) for (int i = A; I <= B; + + i) #define REV (I, A, b) for (int i = a-1; I >= b;--i) #define FOV (I, A, b) for (int i = A; I >= b;--i) #define CLR (A, x) MEMS ET (A, X, sizeof a) #define CPY (A, X) memcpy (A, x, sizeof a) const int MAXM = 1005; Const int MAXN = 1005; const int MAXQ = 2000000; Const int maxe = 2000000; Const int INF = 0x3f3f3f3f; struct Edge {int V, c, N; Edge () {}edge (int v, int c, int n): V (v), C (c), n (n) {}}, struct NetWork {Edge e[maxe]; int H[MAXN], cn TE; int D[MAXN], CUR[MAXN], NUM[MAXN], PRE[MAXN]; int Q[MAXQ], head, tail; int n, m, k; int s, T, NV; int flow; I NT ROW[MAXN], COL[MAXN]; int G[MAXM][MAXM]; int VIS[MAXN]; void init () {cnte = 0; CLR (H,-1);} void Addedge (int u, int v, int c) {E[cnte] = Edge (V, C, H[u]); H[u] = Cnte + +; E[cnte] = Edge (u, 0, h[v]); H[V] = Cnte + +;} void Rev_bfs () {CLR (d,-1); CLR (num, 0); head = tail = 0; Q[tail + +] = t;d [t] = 0; num[d[t]] = 1; while (head! = tail) {int u = q[head + +]; for (int i = h[u]; ~i; i = E[I].N {int v = e[i].v, if (~d[v]) continue;d [v] = D[u] + 1; num[d[v]] + +; Q[tail + +] = V;}}} int Isap () {CPY (cur, H); Rev_bfs (); flow = 0; int u = pre[s] = s, i; while (D[s] < NV) {if (U = = t) {int f = INF, POS; for (i = s; I! = t; i = E[CUR[I]].V) if (F > e[cur[i]].c) {f = e[cur[i]].c;p os = i;} for (i = s; I! = t; i = E[CUR[I]].V) {e[cur[i]].c-= f; E[cur[i] ^ 1].c + = f; Flow + = f; u = pos;} for (i = cur[u]; ~i, i = E[I].N) if (e[i].c && d[u] = = D[E[I].V] + 1) break; if (~i) {Cur[u] = i;p re[e[i].v ] = u; u = e[i].v;} else {if (0 = = (--num[d[u]])) break, int mmin = NV, for (i = h[u]; ~i; i = E[I].N) if (e[i].c && mmin > D[E[I].V]) {Cur[u] = i; mmin = d[e[i].v];} D[u] = Mmin + 1; num[d[u]] + +; u = Pre[u];}} return flow;} void put () {printf ("unique\n"); for (U, 1, n) for (int i = h[u]; ~i; i = e[i].n) {int v = E[I].V; G[u][v-n] = e[i ^ 1].c;} For (i, 1, N) for (j, 1, m) printf ("%d%c", G[i][j], J < m? ': ' \ n ');} int dfs (int u, int fa) {if (Vis[u]) return 1; Vis[u] = 1; for (int i = h[u]; ~i; i = e[i].n) {int v = E[I].V; if (v! = FA && e[i].c && v! = s && v! = t) if (DFS (v, u)) return 1;} Vis[u] = 0; return 0;} void Solve () {int sum1 = 0; int sum2 = 0; init (); s = 0; t = n + m + 1; NV = t + 1; For (i, 1, n) {scanf ("%d", &row[i]), Addedge (S, I, Row[i]); SUM1 + = Row[i];} For (I, 1, m) {scanf ("%d", &col[i]), Addedge (i + N, T, Col[i]); sum2 + = Col[i];} For (i, 1, N) for (j, 1, m) Addedge (i, n + j, k); Isap (); if (flow! = SUM1 | | Flow! = sum2) {printf ("Impos Sible\n "); return;} int flag = 1; CLR (Vis, 0); For (i, 1, n) {if (!flag) Break, if (Dfs (i, 0)) flag = 0;} if (!flag) printf ("Not unique\n"); Elseput ();}} NW; int main () {while (~scanf ("%d%d%d", &NW.N, &NW.M, &NW.K)) nw.solve (); return 0;}
"HDU" 4888 Redraw Beautiful Drawings Network Flow "infer if the solution is unique"