Question link: http://vjudge.net/problem/viewProblem.action? Id = 14877
Question:
To burn as many bridges as possible, and to ensure the connectivity of the graphs, ask which bridges cannot be burned.
We can easily see that what cannot be burned is a bridge that must exist as a cut edge.
We use the Tarjan algorithm to calculate the edge. This is a bit different from the cut point. For (u, v) when the vertex is low [v]> = dfn [u], it indicates that U is the cut point, while low [v]> dfn [u] can be described (u, v) it is a cutting edge.
Because the sequence number of the cut edge is required here, when writing the structure of the edge, ID is used to represent the sequence number of the Bridge. Every time we get, B always adds two edges a-> B and B-> A. Because this is an undirected graph, the two edges share an ID.
In addition, it should be noted that this question allows multiple edges to appear in two locations, so we need to use a tag to indicate whether there is a duplicate edge.
Oid addpath (int A, int B, int C)
{
Int I;
For (I = first [a]; I! =-1; I = path [I]. Next)
If (path [I]. Y = B) break;
If (I! =-1) // indicates the duplicate edge.
Path [I]. Tag = 1;
Else {
Path [K]. y = B, path [K]. tag = 0, path [K]. next = first [a], path [K]. id = C; first [a] = K;
K ++;
}
}
Each time a node is searched in depth, the low and dfn values above are constantly updated, and the edges of low [v]> dfn [u] are found and saved to the bridge array, nbridge is used to count the number of bridges
Void DFS (int u, int FA)
{
Visit [u] = 1, dfn [u] = low [u] = tmpdfn ++;
For (INT I = first [u]; I! =-1; I = path [I]. Next ){
Int J = path [I]. Y;
If (! Visit [J]) {
DFS (J, U );
Low [u] = min (low [J], low [u]);
If (low [J]> dfn [u] &! Path [I]. Tag)
Bridge [++ nbridge] = path [I]. ID;
}
Else {
If (J! = FA) low [u] = min (low [u], dfn [J]); // J has been accessed and is not Father's Day. This indicates that a back edge can be formed.
}
}
}
The Code is as follows:
# Include <iostream> # include <cstdio> # include <cstring> # include <algorithm> using namespace STD; # define n 10005 # define m limit 5int tmpdfn, K, nbridge, bridge [m], visit [N], dfn [N], low [N]; int first [N]; struct path {int y, Tag, ID; int next ;} path [2 * m]; void addpath (int A, int B, int c) {int I; for (I = first [a]; I! =-1; I = path [I]. Next) if (path [I]. Y = B) break; if (I! =-1) // indicates the duplicate path [I]. tag = 1; else {path [K]. y = B, path [K]. tag = 0, path [K]. next = first [a], path [K]. id = C; first [a] = K; k ++ ;}} void DFS (int u, int FA) {visit [u] = 1, dfn [u] = low [u] = tmpdfn ++; For (INT I = first [u]; I! =-1; I = path [I]. Next) {Int J = path [I]. Y; If (! Visit [J]) {DFS (J, U); low [u] = min (low [J], low [u]); if (low [J]> dfn [u] &! Path [I]. Tag) Bridge [++ nbridge] = path [I]. ID;} else {If (J! = FA) low [u] = min (low [u], dfn [J]); // J has been accessed and is not Father's Day, it indicates that a back edge can be formed.} int main () {int t, n, m, X, Y; scanf ("% d", & T ); while (t --) {scanf ("% d", & N, & M); k = 0, nbridge = 0, tmpdfn = 1; memset (first, -1, sizeof (first); memset (visit, 0, sizeof (visit); memset (BRIDGE, 0, sizeof (BRIDGE); For (INT I = 1; I <= m; I ++) {scanf ("% d", & X, & Y); addpath (x, y, I); addpath (Y, x, I);} DFS (1, 0); printf ("% d \ n", nbridge); sort (Bridge + 1, Bridge + nbridge + 1 ); for (INT I = 1; I <nbridge; I ++) printf ("% d", bridge [I]); If (nbridge> 0) printf ("% d \ n", bridge [nbridge]); If (T> 0) printf ("\ n");} return 0 ;}
View code