Skip to content

Instantly share code, notes, and snippets.

@cyclotimia
Last active March 29, 2016 08:23
Show Gist options
  • Save cyclotimia/36afd03b409f7465adff to your computer and use it in GitHub Desktop.
Save cyclotimia/36afd03b409f7465adff to your computer and use it in GitHub Desktop.
finding cut points in a graph
/*
задача: https://stepic.org/lesson/%D0%A1%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B0-%D0%B4%D0%B2%D1%83%D1%81%D0%B2%D1%8F%D0%B7%D0%BD%D1%8B%D1%85-%D0%B3%D1%80%D0%B0%D1%84%D0%BE%D0%B2-12342/step/11?unit=6526
Найдите все точки сочленения в графе.
На вход программе подаётся описание графа, состоящее не более чем из 100000 строк.
Каждая строка описывает очередное ребро: содержит два номера вершин, которые данное ребро соединяет.
Номера разделены пробелом. Гарантируется, что ребра определяют связный граф, вершины которого
пронумерованы числами от 0 до некоторого n.
Выведите единственную строку — список номеров точек сочленения графа через пробел.
Sample Input:
0 1
1 2
2 0
3 2
4 3
4 2
5 4
Sample Output:
2 4
*/
import java.io.BufferedReader;
import java.io.InputStream;
import java.util.*;
class Pair<T, M> {
private final T first;
private final M second;
// конструктор
private Pair(T value1, M value2) {
this.first = value1;
this.second = value2;
}
// получить первый эл-т пары
public T getFirst() {
return this.first;
}
// получить второй эл-т пары
public M getSecond() {
return this.second;
}
// equals
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Pair<?, ?> pair = (Pair<?, ?>) obj;
if (first != null ? !first.equals(pair.first) : pair.first != null) return false;
return !(second != null ? !second.equals(pair.second) : pair.second != null);
}
// hashcode
@Override
public int hashCode() {
int result = first != null ? first.hashCode() : 0;
result = 31 * result + (second != null ? second.hashCode() : 0);
return result;
}
// конструктор
public static <T, M> Pair of(T value1, M value2) {
return new Pair(value1, value2);
}
}
class Graph {
private int V; // No. of vertices
private LinkedList<Integer> adj[]; // Array of lists for Adjacency List Representation
int time = 0;
static final int NIL = -1;
// Constructor
Graph(int v) {
V = v;
adj = new LinkedList[v];
for (int i = 0; i < v; ++i)
adj[i] = new LinkedList();
}
//Function to add an edge into the graph
void addEdge(int v, int w) {
adj[v].add(w); // Add w to v's list.
adj[w].add(v); //Add v to w's list
}
// A recursive function that find articulation points using DFS
// u --> The vertex to be visited next
// visited[] --> keeps tract of visited vertices
// disc[] --> Stores discovery times of visited vertices
// parent[] --> Stores parent vertices in DFS tree
// ap[] --> Store articulation points
void APUtil(int u, boolean visited[], int disc[],
int low[], int parent[], boolean ap[]) {
// Count of children in DFS Tree
int children = 0;
// Mark the current node as visited
visited[u] = true;
// Initialize discovery time and low value
disc[u] = low[u] = ++time;
// Go through all vertices adjacent to this
Iterator<Integer> i = adj[u].iterator();
while (i.hasNext()) {
int v = i.next(); // v is current adjacent of u
// If v is not visited yet, then make it a child of u
// in DFS tree and recur for it
if (!visited[v]) {
children++;
parent[v] = u;
APUtil(v, visited, disc, low, parent, ap);
// Check if the subtree rooted with v has a connection to
// one of the ancestors of u
low[u] = Math.min(low[u], low[v]);
// u is an articulation point in following cases
// (1) u is root of DFS tree and has two or more chilren.
if (parent[u] == NIL && children > 1)
ap[u] = true;
// (2) If u is not root and low value of one of its child
// is more than discovery value of u.
if (parent[u] != NIL && low[v] >= disc[u])
ap[u] = true;
}
// Update low value of u for parent function calls.
else if (v != parent[u])
low[u] = Math.min(low[u], disc[v]);
}
}
void findCutPoints() {
// Mark all the vertices as not visited
boolean visited[] = new boolean[V];
int disc[] = new int[V];
int low[] = new int[V];
int parent[] = new int[V];
boolean ap[] = new boolean[V]; // To store articulation points
// Initialize parent and visited, and ap(articulation point)
// arrays
for (int i = 0; i < V; i++) {
parent[i] = NIL;
visited[i] = false;
ap[i] = false;
}
// Call the recursive helper function to find articulation
// points in DFS tree rooted with vertex 'i'
for (int i = 0; i < V; i++)
if (visited[i] == false)
APUtil(i, visited, disc, low, parent, ap);
// Now ap[] contains articulation points, print them
for (int i = 0; i < V; i++)
if (ap[i] == true)
System.out.print(i + " ");
}
}
public class Main {
public static void main(String[] args) {
// a set of vertices
Set<Integer> vertices = new HashSet<>();
// a list of edges
List<Pair<Integer, Integer>> edges = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int start = scanner.nextInt();
int end = scanner.nextInt();
// adding those to the set of vertices
vertices.add(start);
vertices.add(end);
// making a pair, adding it to the list of edges
Pair<Integer, Integer> edge = Pair.of(start, end);
edges.add(edge);
}
Graph graph = new Graph(vertices.size());
for (int i = 0; i < edges.size(); i++) {
int a = edges.get(i).getFirst();
int b = edges.get(i).getSecond();
graph.addEdge(a, b);
}
graph.findCutPoints();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment