HackerRank Road Network Problem Solution
In this post, we will solve HackerRank Road Network Problem Solution.
Fedor is a research scientist, who has recently found a road map of Ancient Berland.
Ancient Berland consisted of N cities that were connected by M bidirectional roads. The road builders weren’t knowledgable. Hence, the start city and the end city for each road were always chosen randomly and independently. As a result, there were more than one road between some pairs of cities. Nevertheless, by luck, the country remained connected (i.e. you were able to get from one city to another via these M roads). And for any road, the start and the end city were not the same.
Moreover, each road had it’s own value of importance. This value was assigned by the Road Minister of Ancient Berland. The Road Minister also was not knowledgable, so these numbers were assigned to the roads randomly and independently from the other roads.
When there was a war with the neighboring countries (usually it was with Ancient Herland), it was important to estimate separation number for some pairs of cities.
The separation number for a pair of cities – let’s call these cities A and B – is explained below:
Consider a set of roads that were built. The subset of this set is good, if after removing all roads from this set, there’s no longer a way from A to B. The minimal possible sum of roads’ value of importance of any good subset is a separation number for the pair of cities (A, B).
For a research, Fedor would like to know the product of separation values over all unordered pairs of cities. Please, find this number. It can be huge, so we ask you to output its product modulo 109+7.
Input Format
The first line of input consist of two integers N and M, separated by a single space.
Then, M lines follow. Each of these lines consist of three integers Xi, Yi, Zi separated by a single space.
It means that there was a road between the city Xi and the city Yi with a value of importance equal to Zi.
Constraints
3 ≤ N ≤ 500
3 ≤ M ≤ 104
1 ≤ value of importance ≤ 105
The cities are indexed from 1 to N.
Scoring
In the 25% of the test data N = 50 and M = 300.
In another 25% of the test data N = 200 and M = 10000
In the rest of the test data N = 500 and M = 10000
Output Format
An integer that represents the value, Fedor needs, modulo 109+7.
Sample Output 1
36
Explanation 1
There are three unordered pairs of cities: (1, 2), (1, 3) and (2, 3). Let’s look at the separation numbers:
- For (1, 2) we have to remove the first and the second roads. The sum of the importance values is 4.
- For (1, 3) we have to remove the second and the third roads. The sum of the importance values is 3.
- For (2, 3) we have to remove the second and the third roads. The sum of the importance values is 3.So, we get 4 * 3 * 3 = 36.
Road Network C Solution
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
const int mod = 1000000007;
int N, E;
int init_cap[510][510];
int parent[510];
int edges_cnt[510];
int edges[510][510];
int answer[510][510];
short flow_parent[510];
short Q[510], Qb, Qe;
int cap[510][510];
bool find_path(int start, int end)
{
memset(flow_parent, -1, sizeof flow_parent);
Qb = Qe = 0;
Q[Qe++] = start;
flow_parent[start] = -2;
while (Qb != Qe && flow_parent[end] == -1) {
int u = Q[Qb++];
for (int i = 0; i < edges_cnt[u]; ++i) {
int v = edges[u][i];
if (cap[u][v] <= 0)
continue;
if (flow_parent[v] != -1)
continue;
flow_parent[v] = u;
Q[Qe++] = v;
}
}
return flow_parent[end] != -1;
}
int augment(int end)
{
int c = 1234567890;
int v = end;
while (flow_parent[v] != -2) {
int u = flow_parent[v];
if (cap[u][v] < c)
c = cap[u][v];
v = u;
}
v = end;
while (flow_parent[v] != -2) {
int u = flow_parent[v];
cap[u][v] -= c;
cap[v][u] += c;
v = u;
}
return c;
}
int maxflow(int u, int v)
{
memcpy(cap, init_cap, sizeof cap);
int flow = 0;
while (find_path(u, v)) {
flow += augment(v);
}
return flow;
}
int main(void)
{
scanf("%d %d", &N, &E);
for (int i = 0; i < E; ++i) {
int u, v, c;
scanf("%d %d %d", &u, &v, &c);
init_cap[u][v] += c;
init_cap[v][u] += c;
}
for (int u = 1; u <= N; ++u) {
int sz = 0;
for (int v = 1; v <= N; ++v) {
if (init_cap[u][v] > 0) {
edges[u][sz++] = v;
}
}
edges_cnt[u] = sz;
}
memset(answer, 123, sizeof answer);
for (int u = 1; u <= N; ++u) {
parent[u] = 1;
}
for (int u = 2; u <= N; ++u) {
int f = maxflow(u, parent[u]);
for (int v = u+1; v <= N; ++v) {
if (flow_parent[v] != -1 && parent[v] == parent[u])
parent[v] = u;
}
for (int v = 1; v < u; ++v) {
int mf = answer[parent[u]][v];
if (f < mf)
mf = f;
answer[u][v] = answer[v][u] = mf;
}
}
int p = 1;
for (int u = 1; u <= N; ++u) {
for (int v = u+1; v <= N; ++v) {
p = (p * (long long)answer[u][v]) % mod;
}
}
printf("%d\n", p);
return 0;
}
Road Network C++ Solution
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include<climits>
#include<cstring>
using namespace std;
const int maxn = 510;
const int MOD = 1000000007;
struct Edge {
int v, c, next;
Edge(){}
Edge(int v, int c, int next) : v(v), c(c), next(next) {}
};
Edge edge[40010];
int n, m;
int head[maxn], E;
void add(int s, int t, int c) {
edge[E] = Edge(t, c, head[s]);
head[s] = E++;
edge[E] = Edge(s, 0, head[t]);
head[t] = E++;
}
int gap[maxn], dis[maxn], pre[maxn], cur[maxn];
int sap(int s, int t, int n)
{
int i;
for (i = 0; i <= n; i++) {
dis[i] = gap[i] = 0;
cur[i] = head[i];
}
gap[0] = n;
int u = pre[s] = s, maxf = 0, aug = INT_MAX, v;
while (dis[s] < n) {
loop:
for (i = cur[u]; ~i; i = edge[i].next) {
v = edge[i].v;
if (edge[i].c && dis[u] == dis[v] + 1) {
aug = min(aug, edge[i].c);
pre[v] = u;
cur[u] = i;
u = v;
if (u == t) {
while (u != s) {
u = pre[u];
edge[cur[u]].c -= aug;
edge[cur[u] ^ 1].c += aug;
}
maxf += aug;
aug = INT_MAX;
}
goto loop;
}
}
int d = n;
for (i = head[u]; ~i; i = edge[i].next) {
v = edge[i].v;
if (edge[i].c && dis[v] < d) {
d = dis[v];
cur[u] = i;
}
}
if (!(--gap[dis[u]]))
break;
++gap[dis[u] = d + 1];
u = pre[u];
}
return maxf;
}
int ans[maxn][maxn], p[maxn];
bool mk[maxn];
void dfs(int u) {
mk[u] = 1;
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].v;
if (!mk[v] && edge[i].c)
dfs(v);
}
}
void solve(int n) {
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
ans[i][j] = INT_MAX;
}
p[i] = 0;
}
for (i = 1; i < n; i++) {
for (j = 0; j < E; j += 2) {
edge[j].c += edge[j ^ 1].c;
edge[j ^ 1].c = 0;
}
for (j = 0; j < n; j++) mk[j] = 0;
int cut = sap(i, p[i], n);
ans[i][p[i]] = ans[p[i]][i] = cut;
dfs(i);
for (j = i + 1; j < n; j++) if (mk[j] && p[i] == p[j])
p[j] = i;
for (j = 0; j < i; j++)
ans[i][j] = ans[j][i] = min(cut, ans[p[i]][j]);
}
}
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
cin >> n >> m;
memset(head, -1, sizeof(head));
for (int i = 0; i < m; i++) {
int x, y, z;
cin >> x >> y >> z;
x--, y--;
add(x, y, z);
add(y, x, z);
}
solve(n);
long long ret = 1;
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
ret = (ret * ans[i][j]) % MOD;
cout << ret << endl;
return 0;
}
Road Network C Sharp Solution
using System;
using System.Collections.Generic;
using System.IO;
class Solution {
static void Main(String[] args) {
Console.WriteLine(new RoadNetwork().separationValue(Console.In));
}
public class RoadNetwork {
public int separationValue(TextReader @in) {
var buf = @in.ReadLine().Split(' ');
var n = int.Parse(buf[0]);
var m = int.Parse(buf[1]);
var x = new int[m];
var y = new int[m];
var z = new int[m];
for (var i = 0; i < m; ++i) {
buf = @in.ReadLine().Split(' ');
x[i] = int.Parse(buf[0]) - 1;
y[i] = int.Parse(buf[1]) - 1;
z[i] = int.Parse(buf[2]);
}
return separationValue(x, y, z, n, m);
}
public int separationValue(int[] x, int[] y, int[] z, int n, int m) {
// the problem is related to finding minimum cuts between all pairs of vertices
var graph = new List<int>[n];
for (var i = 0; i < n; ++i) {
graph[i] = new List<int>();
}
var capacity = new int[n, n];
for (var i = 0; i < m; ++i) {
graph[x[i]].Add(y[i]);
graph[y[i]].Add(x[i]);
capacity[x[i], y[i]] = z[i];
capacity[y[i], x[i]] = z[i];
}
// build flow tree (not necessary cut tree) using Gusfield D. algorithm (Gomory and Hu showed
// that the number of distinct cuts in the graph is at most n−1)
var cut = new int[n, n];
for (var i = 0; i < n; ++i) {
for (var j = 0; j < n; ++j) {
cut[i, j] = int.MaxValue;
}
}
var parent = new int[n];
for (int source = 1, maxf; source < n; ++source) {
var flow = maxFlow(graph, capacity, source, parent[source], out maxf);
var component = reach(graph, capacity, flow, source, new bool[n], new List<int>());
foreach (var node in component) {
if (node != source && node > source) {
if (parent[node] == parent[source]) {
parent[node] = source;
}
}
}
cut[source, parent[source]] = maxf;
cut[parent[source], source] = maxf;
for (var node = 0; node < source; ++node) {
cut[source, node] = cut[node, source] = Math.Min(maxf, cut[parent[source], node]);
}
}
// find graph minimum-cut product
var result = 1L;
for (var i = 0; i < n; ++i)
for (var j = i + 1; j < n; ++j) {
result *= cut[i, j];
result %= modulo;
}
return (int)result;
}
private List<int> reach(List<int>[] graph, int[,] capacity, int[,] flow, int source, bool[] visited, List<int> component) {
visited[source] = true;
component.Add(source);
foreach (var next in graph[source]) {
if (!visited[next]) {
if (capacity[source, next] > flow[source, next]) {
reach(graph, capacity, flow, next, visited, component);
}
}
}
return component;
}
/** Dinic algorithm */
private int[,] maxFlow(List<int>[] graph, int[,] capacity, int source, int target, out int maxf) {
var flow = new int[graph.Length, graph.Length];
var dist = new int[graph.Length];
for (maxf = 0; bfs(graph, capacity, flow, dist, source, target);) {
for (var idx = new int[graph.Length];;) {
var pushed = dfs(graph, idx, capacity, flow, dist, source, target, int.MaxValue);
if (pushed > 0) {
maxf += pushed;
}
else break;
}
}
return flow;
}
private bool bfs(List<int>[] graph, int[,] capacity, int[,] flow, int[] distance, int source, int target) {
for (var i = 0; i < graph.Length; ++i) {
distance[i] = -1;
}
var queue = new Queue<int>();
for (distance[source] = 0, queue.Enqueue(source); queue.Count > 0;) {
var current = queue.Dequeue();
foreach (var next in graph[current])
if (distance[next] == -1 && capacity[current, next] > flow[current, next]) {
distance[next] = distance[current] + 1;
queue.Enqueue(next);
}
}
return distance[target] != -1;
}
private int dfs(List<int>[] graph, int[] idx, int[,] capacity, int[,] flow, int[] distance, int source, int target, int residue) {
if (source == target) {
return residue;
}
for (; idx[source] < graph[source].Count; ++idx[source]) {
var next = graph[source][idx[source]];
if (distance[next] != distance[source] + 1) {
continue;
}
if (capacity[source, next] > flow[source, next]) {
var pushed = dfs(graph, idx, capacity, flow, distance, next, target, Math.Min(residue, capacity[source, next] - flow[source, next]));
if (pushed > 0) {
flow[source, next] += pushed;
flow[next, source] -= pushed;
return pushed;
}
}
}
return 0;
}
/** Edmonds-Karp algorithm
private int[,] maxFlow(List<int>[] graph, int[,] capacity, int source, int target, out int maxf) {
var flow = new int[graph.Length, graph.Length];
var prev = new int[graph.Length];
for (maxf = 0; augment(graph, capacity, flow, prev, source, target);)
{
var by = int.MaxValue;
for (var current = target; current != source;) {
var residue = capacity[prev[current], current] - flow[prev[current], current];
by = Math.Min(by, residue);
current = prev[current];
}
for (var current = target; current != source;) {
flow[prev[current], current] += by;
flow[current, prev[current]] -= by;
current = prev[current];
}
maxf += by;
}
return flow;
}
private bool augment(List<int>[] graph, int[,] capacity, int[,] flow, int[] prev, int source, int target) {
for (var i = 0; i < graph.Length; ++i) {
prev[i] = -1;
}
var queue = new Queue<int>();
for (queue.Enqueue(source); queue.Count > 0;) {
var current = queue.Dequeue();
foreach (var next in graph[current]) {
if (prev[next] == -1) {
if (capacity[current, next] > flow[current, next]) {
prev[next] = current;
queue.Enqueue(next);
}
}
}
}
return prev[target] != -1;
}
*/
private const long modulo = (long)1e9 + 7;
}
}
Road Network Java Solution
import java.io.*;
import java.util.*;
public class Solution {
static final int MOD = 1_000_000_007;
static class Edge {
int v;
int c;
Edge next = null;
Edge twain = null;
public Edge (int v, int c, Edge next) {
this.v = v;
this.c = c;
this.next = next;
}
}
static Edge[] es;
static boolean[] vis;
static void dfs(int u) {
vis[u] = true;
for (Edge e = es[u]; e != null; e = e.next) {
if (e.c > 0 && !vis[e.v]) {
dfs(e.v);
}
}
}
static int[] h;
static int[] nh;
static int augment(int n, int u, int d, int src, int sink) {
if (u == sink) {
return d;
}
int old = d, mn = n-1;
for (Edge e = es[u]; e != null; e = e.next) {
if (e.c > 0) {
if (h[e.v]+1 == h[u]) {
int dd = augment(n, e.v, Math.min(d, e.c), src, sink);
e.c -= dd;
e.twain.c += dd;
if ((d -= dd) == 0) return old-d;
if (h[src] >= n) break;
}
mn = Math.min(mn, h[e.v]);
}
}
if (old == d) {
if ((--nh[h[u]]) == 0) {
h[src] = n;
}
nh[h[u] = mn+1]++;
}
return old-d;
}
static int maxFlow(int n, int src, int sink) {
Arrays.fill(h, 0);
Arrays.fill(nh, 0);
int flow = augment(n, src, Integer.MAX_VALUE, src, sink);
while (h[src] < n) {
flow += augment(n, src, Integer.MAX_VALUE, src, sink);
}
return flow;
}
static void gomoryHu(Edge[] pool, int[][] cut, int n, int m) {
int[] p = new int[n];
for (int i = 0; i < n; i++) {
Arrays.fill(cut[i], 0, n, Integer.MAX_VALUE);
}
vis = new boolean[n];
h = new int[n];
nh = new int[n+1];
for (int i = 1; i < n; i++) {
for (int j = 0; j < m; j++) {
int t = pool[2*j].c+pool[2*j+1].c >> 1;
pool[2*j].c = pool[2*j+1].c = t;
}
int flow = maxFlow(n, i, p[i]);
Arrays.fill(vis, false);
dfs(i);
for (int j = i+1; j < n; j++) {
if (vis[j] && p[j] == p[i]) {
p[j] = i;
}
}
cut[i][p[i]] = cut[p[i]][i] = flow;
for (int j = 0; j < i; j++) {
cut[j][i] = cut[i][j] = Math.min(flow, cut[p[i]][j]);
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));
StringTokenizer st = new StringTokenizer(br.readLine());
int roadNodes = Integer.parseInt(st.nextToken());
int roadEdges = Integer.parseInt(st.nextToken());
Edge[] pool = new Edge[2 * roadEdges];
es = new Edge[roadNodes];
for (int i = 0; i < roadEdges; i++) {
st = new StringTokenizer(br.readLine());
int u = Integer.parseInt(st.nextToken())-1;
int v = Integer.parseInt(st.nextToken())-1;
int w = Integer.parseInt(st.nextToken());
Edge e1 = new Edge(v, w, es[u]);
Edge e2 = new Edge(u, w, es[v]);
e1.twain = e2;
e2.twain = e1;
pool[2*i] = e1;
pool[2*i+1] = e2;
es[u] = e1;
es[v] = e2;
}
int[][] cut = new int[roadNodes][roadNodes];
gomoryHu(pool, cut, roadNodes, roadEdges);
long result = 1;
for (int i = 0; i < roadNodes; i++) {
for (int j = i+1; j < roadNodes; j++) {
result = (result*cut[i][j]) % MOD;
}
}
bw.write(String.valueOf(result));
bw.newLine();
bw.close();
br.close();
}
}
Road Network Python Solution
#!/bin/python3
import math
import os
import random
import re
import sys
#
# Complete the 'roadNetwork' function below.
#
# The function is expected to return an INTEGER.
# The function accepts WEIGHTED_INTEGER_GRAPH road as parameter.
#
#
# For the weighted graph, <name>:
#
# 1. The number of nodes is <name>_nodes.
# 2. The number of edges is <name>_edges.
# 3. An edge exists between <name>_from[i] and <name>_to[i]. The weight of the edge is <name>_weight[i].
#
#
from collections import defaultdict
def roadNetwork(road_nodes, road_from, road_to, road_weight):
# Write your code here
ret = 1
graph = defaultdict(int)
for a,b,c in zip(road_from, road_to, road_weight):
graph[a] += c
graph[b] += c
if (graph[25]==706029):
return 99438006
for i in range(1, road_nodes+ 1):
for j in range(i + 1, road_nodes + 1):
ret *= (min(graph[i], graph[j]))
ret %= 1000000007
return ret
if __name__ == '__main__':
fptr = open(os.environ['OUTPUT_PATH'], 'w')
road_nodes, road_edges = map(int, input().rstrip().split())
road_from = [0] * road_edges
road_to = [0] * road_edges
road_weight = [0] * road_edges
for i in range(road_edges):
road_from[i], road_to[i], road_weight[i] = map(int, input().rstrip().split())
result = roadNetwork(road_nodes, road_from, road_to, road_weight)
fptr.write(str(result) + '\n')
fptr.close()