From 4f887bee84a39deb2c474b503a94ebaf60ca0a20 Mon Sep 17 00:00:00 2001
From: Bruno Freitas Tissei <bft15@inf.ufpr.br>
Date: Tue, 12 Mar 2019 16:45:40 -0300
Subject: [PATCH] Add URI1128 and fix tarjan

Signed-off-by: Bruno Freitas Tissei <bft15@inf.ufpr.br>
---
 algorithms/graph/articulations_bridges.cpp |   3 +
 algorithms/graph/tarjan.cpp                |  56 +++++++----
 contests/Cadernaveis/MANUT.cpp             |   3 +-
 contests/Cadernaveis/TUBOS.cpp             |  81 ++++++++++++++++
 contests/Cadernaveis/URI1128.cpp           | 103 +++++++++++++++++++++
 5 files changed, 228 insertions(+), 18 deletions(-)
 create mode 100644 contests/Cadernaveis/TUBOS.cpp
 create mode 100644 contests/Cadernaveis/URI1128.cpp

diff --git a/algorithms/graph/articulations_bridges.cpp b/algorithms/graph/articulations_bridges.cpp
index 4943220..5cab796 100644
--- a/algorithms/graph/articulations_bridges.cpp
+++ b/algorithms/graph/articulations_bridges.cpp
@@ -67,8 +67,11 @@ void dfs(int x) {
  * @param x root vertex 
  */
 void tarjan(int n) {
+  mset(L, 0);
+  mset(visited, 0);
   mset(parent, -1);
 
+  // Apply tarjan in every component
   for (int i = 0; i < n; ++i)
     if (!visited[i])
       dfs(i);
diff --git a/algorithms/graph/tarjan.cpp b/algorithms/graph/tarjan.cpp
index dac3ee0..8c6799c 100644
--- a/algorithms/graph/tarjan.cpp
+++ b/algorithms/graph/tarjan.cpp
@@ -1,57 +1,79 @@
 /**
- * Tarjan - Strongly Connected Components
+ * Tarjan - Strongly Connected Components (SCC)
  *
  * Complexity (Time): O(V + E)
  * Complexity (Space): O(V + E)
  */
 
+stack<int> S;
 vector<int> graph[MAX];
-vector<int> scc[MAX];
 
-stack<int> S;
 int ncomp, ind;
-int cont[MAX], parent[MAX];
-int low[MAX], L[MAX];
+int visited[MAX];
+
+// The id of a node x (id[x]) is the order in which x was visited in the DFS
+int id[MAX];
+
+// The low-link value of a node x (low[x]) is defined as the smallest id
+// of another node reachable from x when doing a DFS
+int low[MAX];
+
+// scc[i] contains the i-th SCC stored as a vector with the ids of the
+// vertices in it
+vector<int> scc[MAX];
 
 /**
  * Fills SCC with strongly connected components of graph.
  * @param x any vertex
  */
 void dfs(int x) {
-  L[x] = ind;
-  low[x] = ind++;
-  cont[x] = 1;
+  id[x] = low[x] = ind++;
+  visited[x] = 1;
+
   S.push(x);
 
   for (auto i : graph[x])
-    if (L[i] == -1) {
+    if (id[i] == -1) {
       dfs(i);
+
+      // After the DFS, low[i] might have changed, in that case, low[x]
+      // should be updated if a lower value has been found
       low[x] = min(low[x], low[i]);
-    } else if (cont[i])
-      low[x] = min(low[x], L[i]);
 
-  if (low[x] == L[x]) {
+    // If i has been visited, then i is "above" (has smaller id then x), 
+    // meaning that the edge (x,i) is a "back edge"
+    } else if (visited[i])
+      low[x] = min(low[x], id[i]);
+
+  // A SCC was found
+  if (low[x] == id[x]) {
     int w;
-    ncomp++;
 
+    // Every node on top of x in the stack belongs to the SCC found
     do {
       w = S.top(); S.pop();
-      cont[w] = 0;
+      visited[w] = 0;
       scc[ncomp].pb(w);
     } while (w != x);
+
+    ncomp++;
   }
 }
 
 /**
- * Return number of SCCs.
+ * Returns number of SCCs.
  * @param n number of vertices
  */
 int tarjan(int n) {
-  mset(L, -1);
+  mset(id, -1);
   ncomp = ind = 0;
 
   for (int i = 0; i < n; ++i)
-    if (L[i] == -1)
+    scc[i].clear();
+
+  // Apply tarjan in every component
+  for (int i = 0; i < n; ++i)
+    if (id[i] == -1)
       dfs(i);
 
   return ncomp;
diff --git a/contests/Cadernaveis/MANUT.cpp b/contests/Cadernaveis/MANUT.cpp
index 286be05..ceec4bf 100644
--- a/contests/Cadernaveis/MANUT.cpp
+++ b/contests/Cadernaveis/MANUT.cpp
@@ -52,10 +52,11 @@ void dfs(int x) {
 }
 
 void tarjan(int n) {
+  mset(L, 0);
   mset(visited, 0);
   mset(parent, -1);
-  mset(L, 0);
   articulations.clear();
+
   dfs(n);
 
   sort(all(articulations));
diff --git a/contests/Cadernaveis/TUBOS.cpp b/contests/Cadernaveis/TUBOS.cpp
new file mode 100644
index 0000000..2a94641
--- /dev/null
+++ b/contests/Cadernaveis/TUBOS.cpp
@@ -0,0 +1,81 @@
+#include <bits/stdc++.h>
+
+#define MAX 1010
+#define EPS 1e-6
+#define MOD 1000000007
+#define inf 0x3f3f3f3f
+#define llinf 0x3f3f3f3f3f3f3f3f
+
+#define fi first
+#define se second
+#define pb push_back
+#define ende '\n'
+
+#define all(x) (x).begin(), (x).end()
+#define rall(x) (x).rbegin(), (x).rend()
+#define mset(x, y) memset(&x, (y), sizeof(x))
+
+using namespace std; 
+
+typedef long long ll;
+typedef pair<int,int> ii;
+
+vector<int> graph[MAX];
+int visited[MAX], parent[MAX];
+
+int L[MAX];
+int low[MAX];
+vector<ii> bridges;
+
+void dfs(int x) {
+  int child = 0;
+  visited[x] = 1;
+
+  for (auto i : graph[x]) {
+    if (!visited[i]) {
+      child++;
+      parent[i] = x;
+
+      low[i] = L[i] = L[x] + 1;
+      dfs(i);
+
+      low[x] = min(low[x], low[i]);
+
+      if (low[i] > L[x])
+        bridges.pb(ii(x, i));
+
+    } else if (parent[x] != i)
+      low[x] = min(low[x], L[i]);
+  }
+}
+
+void tarjan(int n) {
+  mset(visited, 0);
+  mset(parent, -1);
+  mset(L, 0);
+  bridges.clear();
+  dfs(n);
+}
+
+int main() {
+  ios::sync_with_stdio(0);
+  cin.tie(0);
+
+  int n, m;
+  while (cin >> n >> m && (n || m)) {
+    for (int i = 0; i < n; ++i)
+      graph[i].clear();
+
+    for (int i = 0; i < m; ++i) {
+      int x, y; cin >> x >> y;
+      x--, y--;
+      graph[x].pb(y);
+      graph[y].pb(x);
+    }
+
+    tarjan(0);
+    cout << (bridges.size() ? "N" : "S") << ende;
+  }
+
+  return 0;
+}
diff --git a/contests/Cadernaveis/URI1128.cpp b/contests/Cadernaveis/URI1128.cpp
new file mode 100644
index 0000000..4e48af8
--- /dev/null
+++ b/contests/Cadernaveis/URI1128.cpp
@@ -0,0 +1,103 @@
+#include <bits/stdc++.h>
+
+#define MAX 2010
+#define EPS 1e-6
+#define MOD 1000000007
+#define inf 0x3f3f3f3f
+#define llinf 0x3f3f3f3f3f3f3f3f
+
+#define fi first
+#define se second
+#define pb push_back
+#define ende '\n'
+
+#define all(x) (x).begin(), (x).end()
+#define rall(x) (x).rbegin(), (x).rend()
+#define mset(x, y) memset(&x, (y), sizeof(x))
+
+using namespace std; 
+
+typedef long long ll;
+typedef pair<int,int> ii;
+
+stack<int> S;
+vector<int> graph[MAX];
+
+int ncomp, ind;
+int visited[MAX];
+
+int id[MAX];
+
+int low[MAX];
+
+vector<int> scc[MAX];
+
+void dfs(int x) {
+  id[x] = low[x] = ind++;
+  visited[x] = 1;
+
+  S.push(x);
+
+  for (auto i : graph[x])
+    if (id[i] == -1) {
+      dfs(i);
+
+      low[x] = min(low[x], low[i]);
+
+    } else if (visited[i])
+      low[x] = min(low[x], id[i]);
+
+  if (low[x] == id[x]) {
+    int w;
+
+    do {
+      w = S.top(); S.pop();
+      visited[w] = 0;
+      scc[ncomp].pb(w);
+    } while (w != x);
+
+    ncomp++;
+  }
+}
+
+int tarjan(int n) {
+  mset(id, -1);
+  ncomp = ind = 0;
+
+  for (int i = 0; i < n; ++i)
+    scc[i].clear();
+
+  for (int i = 0; i < n; ++i)
+    if (id[i] == -1)
+      dfs(i);
+
+  return ncomp;
+}
+
+
+int main() {
+  ios::sync_with_stdio(0);
+  cin.tie(0);
+
+  int n, m;
+  while (cin >> n >> m && (n || m)) {
+    for (int i = 0; i < n; ++i)
+      graph[i].clear();
+
+    for (int i = 0; i < m; ++i) {
+      int v, w, p; cin >> v >> w >> p;
+      v--, w--;
+      if (p == 1)
+        graph[v].pb(w);
+      else {
+        graph[v].pb(w);
+        graph[w].pb(v);
+      }
+    }
+
+    int ans = tarjan(n);
+    cout << (ans == 1) << ende;
+  }
+
+  return 0;
+}
-- 
GitLab