Reprinted please indicate the source, thank youHttp://blog.csdn.net/ACM_cxlove? Viewmode = Contents
By --- cxlove
Question: there are multiple trees for edge deletion. Note that the "Tree" here may have loops, and the shape may be very strange.
We useThe fusion Principle: Nodes in any ring can be merged into one point without changing the graph.SGValue. (We will refer to it as the fusion principle below)
The fusion principle allows us to simplify any root graph into an equivalent one. You can use the colon principle (that isColon
Principle.
We will find that the ring with an odd edge can be simplified to an edge, and the ring with an even edge can be simplified to a node.
In this step, it is obvious that we can find the ring in the graph and determine the number of nodes in the ring for processing.
Use TarjanAlgorithmFind the strongly connected component. After all, it is not a graph theory. It is currently used... Understanding
Duplicate edges may occur. The processing of duplicate edges is that if an even Edge exists between two points, it is treated as an even ring and converted into a vertex; otherwise, it is retained.
After converting a graph into the desired tree, it is a classic edge deletion game.
The SG value of the leaf node is 0, and the SG value of the intermediate node is the exclusive or sum after the SG value of all its subnodes plus 1.
At last, you can create a nim for multiple trees.
# Include <iostream> # include <cstdio> # include <ctime> # include <cstring> # include <algorithm> # include <cstdlib> # include <vector> # Define c 240 # define time 10 # define INF 1 <25 # define ll long longusing namespace STD; vector <int> edge [105]; // adjacent table int mat [105] [105]; // Number of edge storage int low [105], DFA [105]; // Tarjan parameter int s [105], top; // stack bool instack [105]; bool vis [105]; // After Tarjan finds the ring, mark unnecessary points out void Tarjan (int u, int pre, int depth) {LOW [u] = DFA [u] = depth; s [top ++] = u; instack [u] = true; For (INT I = 0; I <edge [u]. size (); I ++) {int v = edge [u] [I]; If (V = pre & mat [u] [v]> 1) {// determine the duplicate edge if (MAT [u] [v] % 2 = 0) vis [u] = true; continue;} If (! DFA [v]) {Tarjan (v, U, depth + 1); low [u] = min (low [u], low [v]);} else if (V! = Pre & instack [v]) low [u] = min (low [u], DFA [v]);} if (DFA [u] = low [u]) {int CNT = 1; top --; while (s [Top]! = U) {vis [s [top --] = true; CNT ++;} If (CNT & 1) // If the node is odd, keep one vertex, including U, that is, two vertices, and keep one edge vis [s [top + 1] = false ;}} int get_sg (int u, int pre) {int ret = 0; For (INT I = 0; I <edge [u]. size (); I ++) {int v = edge [u] [I]; If (! Vis [v] & V! = Pre) RET ^ = (1 + get_sg (v, u);} return ret;} int main () {int K, n, m; while (scanf ("% d", & K )! = EOF) {int ret = 0; while (k --) {scanf ("% d", & N, & M); For (INT I = 1; I <= N; I ++) edge [I]. clear (); memset (MAT, 0, sizeof (MAT); memset (low, 0, sizeof (low); memset (DFA, 0, sizeof (DFA )); memset (instack, false, sizeof (instack); memset (VIS, false, sizeof (VIS); Top = 0; while (M --) {int U, V; scanf ("% d", & U, & V); MAT [u] [v] ++; MAT [v] [u] ++; edge [u]. push_back (V); edge [v]. push_back (U);} Tarjan (1,-1, 1); RET ^ = get_sg (1,-1);} Pu TS (Ret? "Sally": "Harry");} return 0 ;}