Because there are too many questions, errors may occur during the update process. You are welcome to discuss them. ^_^...
Question 1: Ultraviolet A 11624 fire
In the two-dimensional maze, there are some fire points (maybe more than one) that give you the initial position. People and fire points are moving one cell to the adjacent grid every second, ask whether the fire can reach the border before it reaches. If yes, output the shortest time.
Analysis: For fire points, we can pre-process all the fire points into the queue, and then use BFs to process the shortest arrival time of all the burn-able grids. Then, BFs is used to calculate the shortest boundary that a person can reach...
# Include <cstdio> # include <cstring> # include <iostream> using namespace STD; const int x = 1005; int dirx [] = }; int diry [] = {0,-1, 1}; int N; int m; bool use [x] [X]; int TT [x] [x]; char map [x] [X]; struct node {int X, Y, step; node (INT _ x, int _ y, int _ step) {x = _ x; y = _ y; step = _ step; }}; struct point {int X, Y, step; point () {} Point (INT _ x, int _ y, int _ step) {x = _ x; y = _ y; step = _ step;} Q [x * X]; bool out (int x, in T y) {return x> = n | Y> = M | x <0 | Y <0;} int BFS (INT Sx, int SY) {memset (use, false, sizeof (use); int head = 0; int tail = 0; Q [tail ++] = point (sx, Sy, 0 ); while (Head <tail) {point pre = Q [head ++]; int x = pre. x; int y = pre. y; If (x = 0 | Y = 0 | x = n-1 | Y = m-1) return pre. step; pre. step ++; For (INT I = 0; I <4; I ++) {int dx = dirx [I] + X; int DY = diry [I] + Y; if (Out (dx, Dy) continue; If (use [dx] [dy] | TT [dx] [dy] <= pre. ste P | map [dx] [dy] = '#') continue; use [dx] [dy] = true; Q [tail ++] = point (dx, dy, pre. step) ;}} return-1 ;}void Init () {memset (use, false, sizeof (use); int head = 0; int tail = 0; for (INT I = 0; I <n; I ++) for (Int J = 0; j <m; j ++) if (Map [I] [J] = 'F') Q [tail ++] = point (I, j, 0); While (Head <tail) {point pre = Q [head ++]; int x = pre. x; int y = pre. y; TT [x] [Y] = min (TT [x] [Y], pre. step ++); For (INT I = 0; I <4; I ++) {int dx = Dirx [I] + X; int DY = diry [I] + Y; If (Out (dx, Dy) continue; if (use [dx] [dy] | map [dx] [dy] = '#') continue; use [dx] [dy] = true; Q [tail ++] = point (dx, Dy, pre. step) ;}}void solve () {CIN >> N; CIN >>> m; For (INT I = 0; I <n; I ++) scanf ("% s", map [I]); memset (TT, 0x3f, sizeof (TT); int Sx, Sy; SX = Sy = 0; for (INT I = 0; I <n; I ++) for (Int J = 0; j <m; j ++) if (Map [I] [J] = 'J') {SX = I; Sy = J;} Init (); int OK = BFS (sx, Sy ); if (OK =-1) Puts ("impossible"); else printf ("% d \ n", OK + 1);} int main () {freopen ("sum. in "," r ", stdin); int ncase; CIN> ncase; while (ncase --! = 0) solve (); Return 0 ;}
Question 2: the monocycle
A unicorhole is divided into five parts, each of which has a color. At the beginning, the unicorhole is oriented to the north and the bottom of the unicorhole is green, now, a unicycles can move a grid a second or move the direction to the left or right. Now I want to ask how to move a unicycles to reach the destination and the bottom color is green in the shortest time. (A two-dimensional maze, which cannot be moved forward when encountering obstacles)
Analysis: Add two-dimensional question to the original two-dimensional maze. Visit [x] [y] [direction] [color] indicates the lattice [x, y. The others are basically the same as the two-dimensional maze ~~
# Include <iostream> # include <cstring> # include <cstdio> # include <queue> using namespace STD; const int x = 26; const int direction = 4; const int color = 5; bool use [x] [x] [direction] [color]; int n, m; char map [x] [X]; int Sx, Sy, ex, ey; int dirx [] = {-,}; int diry [] = {, 0,-1}; struct node {int X, Y; int D, C; int step; node () {} node (INT _ x, int _ y, int _ d, int _ c, int _ step ): X (_ x), y (_ y), D (_ d), C (_ C), step (_ step) {}}; bool out (int x, int y) {return x <0 | Y <0 | x> = n | Y> = m;} int ABS (int x) {return max (X, -x);} void BFS () {memset (use, false, sizeof (use); queue <node> q; use [SX] [sy] [0] [0] = true; q. push (node (sx, Sy, 0, 0); While (Q. size () {node pre = Q. front (); q. pop (); int x = pre. x; int y = pre. y; int d = pre. d; int c = pre. c; If (x = ex & Y = ey & Pre. C = 0) {printf ("minimum time = % d sec \ n", pre. step); return;} pre. step ++; For (INT I = 0; I <4; I ++) {If (ABS (I-d) = 2) continue; if (I = d) {int dx = dirx [I] + X; int DY = diry [I] + Y; int Dc = (C + 1) % 5; int dd = I; If (Out (dx, Dy) | map [dx] [dy] = '#' | use [dx] [dy] [DD] [DC]) continue; use [dx] [dy] [DD] [DC] = true; q. push (node (dx, Dy, DD, DC, pre. step);} else {If (use [x] [y] [I] [c]) continue; use [x] [y] [I] [c] = true; q. push (node (x, y, I, C, pre. step) ;}} puts ("destination not reachable");} int main () {freopen ("sum. in "," r ", stdin); int ncase = 0; while (CIN> N> M, N | M) {If (ncase) puts (""); printf ("case # % d \ n", ++ ncase); For (INT I = 0; I <n; I ++) {scanf ("% s", map [I]); For (Int J = 0; j <m; j ++) {If (Map [I] [J] ='s ') {SX = I; Sy = J ;} else if (Map [I] [J] = 'T') {EX = I; ey = J ;}} BFS ();} return 0 ;}
Question 3: The neck.pdf
Beads are composed of two parts, each of which has a color. If two beads of the same color can be connected together, I am wondering if I can concatenate all the beads. If possible, a series method is provided.
Analysis: Find the Euler's loop, regard each color as a vertex on the graph, and then construct a undirected edge for each bead, first determine whether there is an odd vertex, if there is, the Euler loop does not exist. Otherwise, you can use DFS once. Note that multiple identical edges may exist in the figure (I have not tested it), so you can delete one edge each time you use DFS.
# Include <iostream> # include <cstdio> # include <cstring> using namespace STD; const int x = 60; const int n = 50; int map [x] [x]; int ID [X]; int m; void DFS (int x) {for (INT y = 1; y <= N; y ++) {If (Map [x] [Y]> 0) {map [x] [Y] --; Map [y] [x] --; DFS (y ); cout <Y <"" <x <Endl ;}} int main () {freopen ("sum. in "," r ", stdin); int ncase, X, Y, CNT = 0; CIN> ncase; while (ncase --) {If (CNT) puts (""); printf ("case # % d \ n", ++ CNT); memse T (MAP, 0, sizeof (MAP); memset (ID, 0, sizeof (ID); scanf ("% d", & M); While (M --) {scanf ("% d", & X, & Y); map [x] [Y] ++; Map [y] [x] ++; id [x] ++; Id [y] ++;} bool OK = true; For (INT I = 1; I <= N; I ++) {If (ID [I] & 1) {OK = false; puts ("some beads may be lost"); break ;}} if (! OK) continue; DFS (x);} return 0 ;}
Question 7: ICPC 4287 proving equivalences
A can launch B, B can launch c, and now ask how many relationships are added to make all relationships equal to each other.
Analysis: it is not difficult to think of constructing a directed graph, then finding the strongly connected component in the graph, and then finding Max (ID, OD) after shrinking ). Id indicates the number of vertices whose input degree is 0, and OD indicates the number of outbound vertices whose input degree is 0. Note that when there is only one connected block, the answer should be 0 (all elements in the contraction point are equivalent to each other)
# Include <iostream> # include <cstdio> # include <cstring> using namespace STD; const int maxn = 50005; const int maxm = 100005; int po [maxn], Tol; int stack [maxn], dfn [maxn], low [maxn], Father [maxn], bcnt, depth, top; bool instack [maxn]; int ID [maxn], od [maxn]; int n, m; struct node {int y, next;} edge [maxm]; void DFS (int x) {// Recursive Implementation of Tarjan Algorithm Low [x] = dfn [x] = ++ depth; instack [x] = true; stack [++ top] = x; int y; for (INT I = po [X]; I; I = edge [I]. next) {Y = edge [I]. y; If (! Dfn [y]) {DFS (y); low [x] = min (low [X], low [y]);} else if (instack [y]) low [x] = min (low [X], dfn [y]);} If (low [x] = dfn [x]) {++ bcnt; do {Y = stack [top --]; instack [y] = false; father [y] = bcnt;} while (X! = Y) ;}} void Tarjan () {memset (instack, false, sizeof (instack); memset (dfn, 0, sizeof (dfn )); top = bcnt = depth = 0; For (INT I = 1; I <= N; I ++) if (! Dfn [I]) DFS (I); If (bcnt = 1) {puts ("0"); return;} memset (ID, 0, sizeof (ID )); memset (OD, 0, sizeof (OD); For (INT x = 1; x <= N; X ++) for (Int J = po [X]; J; j = edge [J]. next) {int y = edge [J]. y; If (father [x]! = Father [y]) {OD [Father [x] ++; Id [Father [y] ++ ;}} int id_cnt = 0, od_cnt = 0; for (INT I = 1; I <= bcnt; I ++) {If (! Id [I]) id_cnt ++; If (! Od [I]) od_cnt ++;} cout <max (id_cnt, od_cnt) <Endl;} void add (INT X, int y) {edge [++ tol]. y = y; edge [tol]. next = po [X]; po [x] = tol;} int main () {freopen ("sum. in "," r ", stdin); int ncase; CIN> ncase; while (ncase --) {memset (PO, 0, sizeof (PO); Tol = 0; int X, Y; CIN> N> m; while (M --) {scanf ("% d", & X, & Y); add (X, y);} Tarjan ();} return 0 ;}
Question 8: Ultraviolet A 11324The largest clique
Start at a certain point and find the maximum number of nodes that can be walked at a time
Analysis:
Tarjan calculates GCC, and then constructs a new graph. The new graph is a dag. For the Dag, use DP to find the longest path. The DP transition equation is DP [x] = size [x] + max (DP [y]). After the point is scaled down, the edge X to Y is displayed. You can simply perform a memory search, specific implementationCode
# Include <iostream> # include <cstring> # include <cstdio> # include <vector> using namespace STD; const int maxn = 1005; const int maxm = 50005; # define debug puts ("here"); int dfn [maxn], low [maxn], stack [maxn], Father [maxn], bcnt, top, depth; bool instack [maxn]; int po [maxn], Tol, n, m; int ID [maxn]; int DP [maxn]; int sum [maxn]; vector <int> VEC [maxn]; struct node {int y, next;} edge [maxm]; void add (int x, int y) {edge [++ tol]. Y = Y; edge [tol]. next = po [X]; po [x] = tol;} void DFS (int x) {// Recursive Implementation of the Tarjan algorithm low [x] = dfn [x] = ++ depth; instack [x] = true; stack [++ top] = x; int y; for (INT I = po [X]; I; I = edge [I]. next) {Y = edge [I]. y; If (! Dfn [y]) {DFS (y); low [x] = min (low [X], low [y]);} else if (instack [y]) low [x] = min (low [X], dfn [y]);} If (low [x] = dfn [x]) {++ bcnt; do {Y = stack [top --]; instack [y] = false; father [y] = bcnt;} while (X! = Y) ;}} void Tarjan (){
Memset (instack, false, sizeof (instack); memset (low, 0, sizeof (low); memset (dfn, 0, sizeof (dfn )); top = bcnt = depth = 0; For (INT I = 1; I <= N; I ++) if (! Dfn [I]) DFS (I);} int F (INT X) {// evaluate the longest path of Dag if (DP [x]) return DP [X]; int ans = 0; For (INT I = 0; I <(INT) VEC [X]. size (); I ++) {// starting from all the edges of X, find the maximum path int y = VEC [x] [I]; ans = max (ANS, f (y); // transfer equation} DP [x] = ans + sum [X]; return DP [X];} void DAG () {memset (ID, 0, sizeof (ID); memset (sum, 0, sizeof (SUM); memset (DP, 0, sizeof (DP); For (INT I = 1; I <= N; I ++) VEC [I]. clear (); For (INT x = 1; x <= N; X ++) {// create a new graph for (Int J = po [X]; j = ed GE [J]. Next) {int y = edge [J]. Y; If (father [x]! = Father [y]) {VEC [Father [x]. push_back (father [y]); Id [Father [y] ++;} sum [Father [x] ++; // count the number of nodes of all source images contained by the node after each contraction} int ans = 0; For (INT I = 1; I <= bcnt; I ++) if (! Id [I]) ans = max (f (I), ANS); cout <ans <Endl;} int main () {freopen ("sum. in "," r ", stdin); int ncase; CIN> ncase; while (ncase --) {CIN> N> m; int X, Y; memset (PO, 0, sizeof (PO); Tol = 0; while (M --) {scanf ("% d", & X, & Y ); add (x, y);} Tarjan (); DAG ();} return 0 ;}
.....