Question link: http://acm.hdu.edu.cn/showproblem.php? PID = 1, 2242
Given a graph, each vertex has a weight and may have a duplicate edge. You need to delete an edge to divide the graph into two parts, find the difference between the minimum weight and the two parts. If there is no way to divide them into two parts, output impossible.
Solution: Graph Theory and tree DP. If the given graph is a tree, you can use the tree DP to solve the problem. In this case, impssible does not exist. However, the topic does not indicate that the given graph is a tree structure, but may contain two connected components (if any edge is deleted, the connectivity of the connected components cannot be changed ), at this time, we need to compress this dual-connected component into a vertex, then use the compressed vertex to build a tree, and then we can perform DP on the tree, delete an edge (u-> V) to see the difference between the weights of the Child tree rooted in U and the Child tree rooted in v.
After thinking about the above process, the problem becomes how to scale down. It really hurts me. I spent a day watching the strong and double connected components, learn to use the beautiful Trajan algorithm. For detailed algorithms, you can use Baidu and Google. In this article, we use Trajan to find every bridge in the graph, store the vertices on both sides of the bridge into an array, and then use these vertices to reconstruct a tree. A bridge is also called a cut edge. What is that? It can be simply understood as removing this edge, and the connected graph will not be connected. I simply understand it if I do not understand it deeply.
There is a trick in this question, that is, when there is a duplicate edge, this edge should also be processed, so it must be determined.
Test data:
2 2
1 1
1 2
2 1
4 5
1 2 3 4
0 1
1 2
2 0
1 0
1 3
1 0
1
4 3
1 2 3 5
0 1
1 2
2 3
4 3
1 1 1 1
0 1
1 2
2 3
Code:
# Include <stdio. h> # include <math. h> # include <string. h> # define Max 41000 # define min (a, B) (a) <(B )? (A) :( B) struct node {int V, Y; node * Next;}; int n, m, PTR, CNT, sum, top, St [Max]; int tot, BL [Max], vis [Max], Minn, DP [Max]; int dfn [Max], low [Max], Val [Max], index; node * head [Max], tree [Max], bridge [Max]; void initial () {Minn = 2147483647; CNT = sum = tot = 0; PTR = Top = Index = 1; memset (DP, 0, sizeof (DP); memset (dfn, 0, sizeof (dfn); memset (VIS, 0, sizeof (VIS); memset (Head, null, sizeof (head);} void addedge (int x, int y) {tree [PTR]. V = y; tree [PTR]. next = head [X], head [x] = & tree [PTR ++]; tree [PTR]. V = x; tree [PTR]. next = head [Y], head [y] = & tree [PTR ++];} void Trajan (int I, int FA) {node * P = head [I]; int v =-1, flag = 1; ST [++ top] = I, vis [I] = 1; dfn [I] = low [I] = index ++; while (P! = NULL) {If (p-> V = fa & flag) {// remove an edge pointing to the father, that is, a duplicate flag is allowed; P = p-> next; continue;} If (vis [p-> V] = 0) {// Trajan (p-> V, I ); low [I] = min (low [I], low [p-> V]); If (low [p-> V]> dfn [I]) {bridge [++ tot]. V = I; Bridge [tot]. y = p-> V ;}} else if (vis [p-> V] = 1) // return to the parent side Low [I] = min (low [I], dfn [p-> V]); P = p-> next;} vis [I] = 2; // indicates the scaled down point if (low [I] = dfn [I]) {CNT ++; while (V! = I) {v = sT [top --]; BL [v] = CNT; DP [CNT] + = Val [v] ;}} void createnew () {PTR = 1; memset (Head, null, sizeof (head); For (INT I = 1; I <= tot; ++ I) {int x = bl [bridge [I]. v]; int y = bl [bridge [I]. y]; addedge (x, y) ;}} void tree_dp (int v, int Pa) {node * P = head [v]; while (P! = NULL) {If (p-> V! = PA) {tree_dp (p-> V, V); DP [v] + = DP [p-> V];} p = p-> next ;} minn = min (Minn, ABS (Sum-DP [v] * 2);} int main () {int I, J, K, A, B; while (scanf ("% d", & N, & M )! = EOF) {initial (); for (I = 1; I <= N; ++ I) scanf ("% d", & Val [I]), sum + = Val [I]; for (I = 1; I <= m; ++ I) scanf ("% d", & A, & B ), addedge (a + 1, B + 1); Trajan (1, 0); If (TOT = 0) {printf ("impossible \ n"); continue;} createnew (); tree_dp (1, 0); printf ("% d \ n", Minn );}}
This article is original in zeroclock, but it can be reproduced, because we are brothers.