Detect cycle in an undirected graph - algorithm

In order to detect cycle in undirected graph,
following code anf algorithm are given; I am using normal Breadth First traversal along with slight modifications :
void bfsUtil(int s,vector<bool> &visited,vector<int> adj[],vector<int> &visits) {
queue<int> q;
q.push(s);
visits[s]++;
visited[s]=true;
while(!q.empty()) {
int vertex=q.front();
q.pop();
for(int i=0;i<adj[vertex].size();i++) {
if(!visited[adj[vertex][i]]) {
visited[adj[vertex][i]]=true;
q.push(adj[vertex][i]);
visits[adj[vertex][i]]++;
} else {
visits[adj[vertex][i]]++;
}
}
}
}
/* This function is used to detect a cycle in undirected graph
* adj[]: array of vectors to represent graph
* V: number of vertices
*/
bool isCyclic(vector<int> adj[], int V)
{
vector<int> visits(V,0);
vector<bool> visited(V,false);
for(int i=0;i<V;i++){
if(!visited[i]) {
bfsUtil(i,visited,adj,visits);
}
}
for(int i=0;i<visits.size();i++) {
if(visits[i]>2) {
return true;
}
}
return false;
}
Algorithm:
1. Normal Breadth first search and maintaining a count aray for the no of visits of each vertex.
2. If no of visits>2
print cycle is present
else
print no cycle
But i am getting wrong anwer for below test case:
Input:
46 45
0 44 1 23 1 35 1 37 1 38 2 20 2 35 3 13 4 44 5 21 5 36 6 41 7 8 8 18 9 17 9 41 9 45 10 13 10 21 10 33 10 34 10 39 10 42 11 17 12 24 13 44 14 19 15 25 16 34 18 24 19 25 21 24 21 26 22 37 23 28 25 31 25 35 25 40 25 41 25 44 27 43 27 44 29 40 30 34 32 33
Its Correct output is:
0
And Your Code's output is:
1
Where is my algorithm going wrong ?

Your algorithm is wrong. consider a graph of the following edges:
0 - 1
0 - 2
When the current node is 1, it also checks 0 as there is an edge from 1 to 0 too. so it will increment the visits count of 0. Similarly, 2 will also increment the count. So your code will always detect cycles wrongly.
To resolve this, you should keep a parent node for each node, from where the node is visited. When you are checking, you should never consider the edge to the parent.
And finally, you don't need the visits array. If you find an adjacent node that is not parent of current node, but is still visited before, then you can conclude that there is a cycle.
Modifying your code:
bool bfsUtil(int s,vector<bool> &visited,vector<int> adj[],vector<int> &parent) {
queue<int> q;
q.push(s);
visited[s]=true;
while(!q.empty()) {
int vertex=q.front();
q.pop();
for(int i=0;i<adj[vertex].size();i++) {
if(adj[vertex][i] == parent[vertex])
continue;
if(!visited[adj[vertex][i]]) {
visited[adj[vertex][i]]=true;
q.push(adj[vertex][i]);
parent[adj[vertex][i]] = vertex;
} else {
//cycle detected;
return true;
}
}
}
return false;
}
/* This function is used to detect a cycle in undirected graph
* adj[]: array of vectors to represent graph
* V: number of vertices
*/
bool isCyclic(vector<int> adj[], int V)
{
vector<bool> visited(V,false);
vector<int> parent(V, -1); // -1 means no parent assigned
for(int i=0;i<V;i++){
if(!visited[i]) {
if(bfsUtil(i,visited,adj,parent)) return true;
}
}
return false;
}

Related

Algorithm for visiting all grid cells in pseudo-random order that has a guaranteed uniformity at any stage

Context:
I have a hydraulic erosion algorithm that needs to receive an array of droplet starting positions. I also already have a pattern replicating algorithm, so I only need a good pattern to replicate.
The Requirements:
I need an algorism that produces a set of n^2 entries in a set of format (x,y) or [index] that describe cells in an nxn grid (where n = 2^i where i is any positive integer).
(as a set it means that every cell is mentioned in exactly one entry)
The pattern [created by the algorism ] should contain zero to none clustering of "visited" cells at any stage.
The cell (0,0) is as close to (n-1,n-1) as to (1,1), this relates to the definition of clustering
Note
I was/am trying to find solutions through fractal-like patterns built through recursion, but at the time of writing this, my solution is a lookup table of a checkerboard pattern(list of black cells + list of white cells) (which is bad, but yields fewer artifacts than an ordered list)
C, C++, C#, Java implementations (if any) are preferred
You can use a linear congruential generator to create an even distribution across your n×n space. For example, if you have a 64×64 grid, using a stride of 47 will create the pattern on the left below. (Run on jsbin) The cells are visited from light to dark.
That pattern does not cluster, but it is rather uniform. It uses a simple row-wide transformation where
k = (k + 47) mod (n * n)
x = k mod n
y = k div n
You can add a bit of randomness by making k the index of a space-filling curve such as the Hilbert curve. This will yield the pattern on the right. (Run on jsbin)
     
     
You can see the code in the jsbin links.
I have solved the problem myself and just sharing my solution:
here are my outputs for the i between 0 and 3:
power: 0
ordering:
0
matrix visit order:
0
power: 1
ordering:
0 3 2 1
matrix visit order:
0 3
2 1
power: 2
ordering:
0 10 8 2 5 15 13 7 4 14 12 6 1 11 9 3
matrix visit order:
0 12 3 15
8 4 11 7
2 14 1 13
10 6 9 5
power: 3
ordering:
0 36 32 4 18 54 50 22 16 52 48 20 2 38 34 6
9 45 41 13 27 63 59 31 25 61 57 29 11 47 43 15
8 44 40 12 26 62 58 30 24 60 56 28 10 46 42 14
1 37 33 5 19 55 51 23 17 53 49 21 3 39 35 7
matrix visit order:
0 48 12 60 3 51 15 63
32 16 44 28 35 19 47 31
8 56 4 52 11 59 7 55
40 24 36 20 43 27 39 23
2 50 14 62 1 49 13 61
34 18 46 30 33 17 45 29
10 58 6 54 9 57 5 53
42 26 38 22 41 25 37 21
the code:
public static int[] GetPattern(int power, int maxReturnSize = int.MaxValue)
{
int sideLength = 1 << power;
int cellsNumber = sideLength * sideLength;
int[] ret = new int[cellsNumber];
for ( int i = 0 ; i < cellsNumber && i < maxReturnSize ; i++ ) {
// this loop's body can be used for per-request computation
int x = 0;
int y = 0;
for ( int p = power - 1 ; p >= 0 ; p-- ) {
int temp = (i >> (p * 2)) % 4; //2 bits of the index starting from the begining
int a = temp % 2; // the first bit
int b = temp >> 1; // the second bit
x += a << power - 1 - p;
y += (a ^ b) << power - 1 - p;// ^ is XOR
// 00=>(0,0), 01 =>(1,1) 10 =>(0,1) 11 =>(1,0) scaled to 2^p where 0<=p
}
//to index
int index = y * sideLength + x;
ret[i] = index;
}
return ret;
}
I do admit that somewhere along the way the values got transposed, but it does not matter because of how it works.
After doing some optimization I came up with this loop body:
int x = 0;
int y = 0;
for ( int p = 0 ; p < power ; p++ ) {
int temp = ( i >> ( p * 2 ) ) & 3;
int a = temp & 1;
int b = temp >> 1;
x = ( x << 1 ) | a;
y = ( y << 1 ) | ( a ^ b );
}
int index = y * sideLength + x;
(the code assumes that c# optimizer, IL2CPP, and CPP compiler will optimize variables temp, a, b out)

How to make a N×N matrix each of i-th row and i-th column having all the elements 1 to 2N-1?

This question was asked as a puzzle in one Book of Puzzles by RS AGGARWAL, which stated the problem as to build an order N matrix where each i'th row and i'th column combined have all the elements from 1 to 2N-1.
For instance, for N=2
[3,2]
[1,3]
I want to know when is an answer possible for it for which values of N it is possible to make a matrix and how to make it? and write code for it
this has simple solution for square matrices where n is power of 2 so n=1,2,4,8,16,... do not ask me why there surely is some math proof for it ...
The algorithm to create such matrix is easy:
clear matrix (with 0)
loop i through all values i=1,2,3...2n-1
for each i find all locations where i matrix is not yet filled (0) and there is not i present in row and column
fill the position with i and repeat until no such location found.
In C++ something like this:
//---------------------------------------------------------------------------
const int n=8;
int m[n][n];
//---------------------------------------------------------------------------
// compute histogram u[n+n] of values per ith row,col of m[n][n]
void hist_rst(int *u ) { for (int j=0;j<n+n;j++) u[j]=0; }
void hist_row(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[j][i]]=1; }
void hist_col(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[i][j]]=1; }
//---------------------------------------------------------------------------
void matrix_init(int m[n][n])
{
int i,x,y,h[n][n+n];
// clear matrix (unused cells)
for (x=0;x<n;x++)
for (y=0;y<n;y++)
m[x][y]=0;
// clear histograms
for (i=0;i<n;i++) hist_rst(h[i]);
// try to fill values 1..2n-1
for (i=1;i<n+n;i++)
{
// find free position
for (x=0;x<n;x++) if (!h[x][i])
for (y=0;y<n;y++) if (!h[y][i])
if (!m[x][y])
{
// set cell
m[x][y]=i;
h[x][i]=1;
h[y][i]=1;
break;
}
}
}
//---------------------------------------------------------------------------
here few outputs:
1
1 3
2 1
1 5 6 7
2 1 7 6
3 4 1 5
4 3 2 1
1 9 10 11 12 13 14 15
2 1 11 10 13 12 15 14
3 4 1 9 14 15 12 13
4 3 2 1 15 14 13 12
5 6 7 8 1 9 10 11
6 5 8 7 2 1 11 10
7 8 5 6 3 4 1 9
8 7 6 5 4 3 2 1
for non power of 2 matrices you could use backtracking but take in mind even 4x4 matrix will have many iterations to check ... so some heuristics would need to be in place to make it possible in finite time... as brute force is (n+n)^(n*n) so for n=4 there are 281474976710656 combinations to check ...
[edit1] genere&test solution for even n
//---------------------------------------------------------------------------
const int n=6;
int m[n][n];
//---------------------------------------------------------------------------
// compute histogram u[n+n] of values per ith row,col of m[n][n]
void hist_rst(int *u ) { for (int j=0;j<n+n;j++) u[j]=0; }
void hist_row(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[j][i]]=1; }
void hist_col(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[i][j]]=1; }
//---------------------------------------------------------------------------
void matrix_init2(int m[n][n]) // brute force
{
int x,y,a,ax[(n*n)>>1],ay[(n*n)>>1],an,u[n+n];
// clear matrix (unused cells)
for (x=0;x<n;x++)
for (y=0;y<n;y++)
m[x][y]=0;
// main diagonal 1,1,1,1...
for (x=0;x<n;x++) m[x][x]=1;
// 1st row 1,2,3...n
for (x=1;x<n;x++) m[x][0]=x+1;
// cells for brute force
for (an=0,x=0;x<n;x++)
for (y=0;y<x;y++)
if (!m[x][y])
{
ax[an]=x;
ay[an]=y;
an++;
m[x][y]=2;
}
// brute force attack values 2,3,4,5,...,n-1
for (;;)
{
// increment solution
for (a=0;a<an;a++)
{
x=ax[a];
y=ay[a];
m[x][y]++;
if (m[x][y]<=n) break;
m[x][y]=2;
}
if (a>=an) break; // no solution
// test
for (x=0;x<n;x++)
{
hist_rst(u);
hist_col(u,m,x);
hist_row(u,m,x);
for (y=1;y<=n;y++) if (!u[y]) { y=0; x=n; break; }
}
if (y) break; // solution found
}
// mirror other triangle
for (x=0;x<n;x++)
for (y=0;y<x;y++)
m[y][x]=m[x][y]+n-1;
}
//---------------------------------------------------------------------------
however its slow so do not try to go with n>6 without more optimizations/better heuristics... for now it is using triangle+mirror and diagonal + first row hard-coded heuristics.
maybe somehow exploit the fact that each iterated value will be placed n/2 times could speed this up more but too lazy to implement it ...
Here output for n=6:
[ 52.609 ms]
1 2 3 4 5 6
7 1 6 5 3 4
8 11 1 2 4 5
9 10 7 1 6 3
10 8 9 11 1 2
11 9 10 8 7 1
iterating through 5^10 cases ...
As requested by Spektre, here is the 6x6 matrix.
I an interesting property that may be used as heuristic. We need only to solve a triangular matrix because the other half can be easily deduced. We fill the upper (or lower) half of the matrix by values from 1 to n only. We can then complete the matrix by using the property that a[j][i] = 2n + 1 - a[i][j].
Another property I found is that there is a trivial way to place 1, 2 and N in the matrix. The values 1 are all on the diagonal, the values 2 and N are next to the diagonal at a step 2.
Finally, another thing I found is that matrix with odd N have no solutions. It is because the value in a[i][j] belongs to row and column i and row and column j. We thus need an even number of row and columns to store all values.
Here is the 6x6 matrix I found manually.
1 2 3 4 5 6
11 1 6 5 3 4
10 7 1 2 4 5
9 8 11 1 6 3
8 10 9 7 1 2
7 9 8 10 11 1
As we can see 2 + 11 = 6 + 7 = 3 + 10 = 13 = 2*6+1.
Here is a 4x4 matrix
1 2 3 4
7 1 4 3
6 5 1 2
5 6 7 1
Here again 2 + 7 = 4 + 5 = 3 + 6 = 9 = 2*4+1
It is possible to have other permutations of values >N, but with the 2N+1 property we can trivially deduce one triangular matrix from the other.
EDIT
Here is a solution for power two sized matrix. The matrix of size 2048x2048 is generated in 57ms (without printing).
#include <stdio.h>
int **newMatrix(int n) {
int **m = calloc(n, sizeof(int*));
m[0] = calloc(n*n, sizeof(int));
for (int i = 1; i < n; i++)
m[i] = m[0]+i*n;
return m;
}
void printMatrix(int **m, int n) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
printf("%3d ", m[i][j]);
printf("\n");
}
}
void fillPowerTwoMatrix(int **m, int n) {
// return if n is not power two
if (n < 0 || n&(n-1) != 0)
return;
for (int i = 0; i < n; i++)
m[0][i] = i+1;
for (int w = 1; w < n; w *= 2)
for (int k = 0; k < n; k += 2*w)
for (int i = 0; i < w; i++)
for (int j = k; j < k+w; j++) {
m[i+w][j] = m[i][j+w];
m[i+w][j+w] = m[i][j];
}
int k = 2*n+1;
for (int i = 1; i < n; i++)
for (int j = 0; j < i; j++)
m[i][j] = k - m[j][i];
}
int main() {
int n = 16;
int **m = newMatrix(n);
fillPowerTwoMatrix(m, n);
printMatrix(m, n);
return 0;
}
Here is the matrix 16x16. As can be seen there is a symmetry that is exploited to efficiently generate the matrix.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
31 1 4 3 6 5 8 7 10 9 12 11 14 13 16 15
30 29 1 2 7 8 5 6 11 12 9 10 15 16 13 14
29 30 31 1 8 7 6 5 12 11 10 9 16 15 14 13
28 27 26 25 1 2 3 4 13 14 15 16 9 10 11 12
27 28 25 26 31 1 4 3 14 13 16 15 10 9 12 11
26 25 28 27 30 29 1 2 15 16 13 14 11 12 9 10
25 26 27 28 29 30 31 1 16 15 14 13 12 11 10 9
24 23 22 21 20 19 18 17 1 2 3 4 5 6 7 8
23 24 21 22 19 20 17 18 31 1 4 3 6 5 8 7
22 21 24 23 18 17 20 19 30 29 1 2 7 8 5 6
21 22 23 24 17 18 19 20 29 30 31 1 8 7 6 5
20 19 18 17 24 23 22 21 28 27 26 25 1 2 3 4
19 20 17 18 23 24 21 22 27 28 25 26 31 1 4 3
18 17 20 19 22 21 24 23 26 25 28 27 30 29 1 2
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 1

Maximum sum of values with constant sum of indices

I am looking for an efficient algorithm for the following problem:
There is an array with values, i.e. (note that index 0 is omitted on purpose)
Index 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
Value 17, 12, 5, 22, 3, 12, 6, 13, 7, 0, 2, 15
What I need to find is a subset of indices under these constraints:
The number of indices is constant (i.e. 3)
The sum of indices is constant (i.e. 20)
Each index may only appear once (so [2, 9, 9] is not a valid solution)
The sum of values is maximum.
For example if the subset length is 3 and the sum is 20, all possible solutions would be
Indices: [1, 7, 12] Sum of values: 17 + 6 + 15 = 38
Indices: [1, 8, 11] Sum of values: 17 + 13 + 2 = 32
Indices: [1, 9, 10] Sum of values: 17 + 7 + 0 = 24
Indices: [2, 6, 12] Sum of values: 12 + 12 + 15 = 39
Indices: [2, 7, 11] Sum of values: 12 + 6 + 2 = 20
Indices: [2, 8, 10] Sum of values: 12 + 13 + 0 = 25
Indices: [3, 5, 12] Sum of values: 5 + 3 + 15 = 23
Indices: [3, 6, 11] Sum of values: 5 + 12 + 2 = 19
Indices: [3, 7, 10] Sum of values: 5 + 6 + 0 = 11
Indices: [3, 8, 9] Sum of values: 5 + 13 + 7 = 25
Indices: [4, 5, 11] Sum of values: 22 + 3 + 2 = 27
Indices: [4, 6, 10] Sum of values: 22 + 12 + 0 = 34
Indices: [4, 7, 9] Sum of values: 22 + 6 + 7 = 35
Indices: [5, 6, 9] Sum of values: 3 + 12 + 7 = 22
Indices: [5, 7, 8] Sum of values: 3 + 6 + 13 = 22
of which [2, 6, 12] is the optimal solution because it has the maximum sum of values.
At the moment I run through all possible combinations using a slightly modified partition algorithm which grows exponentially as the sum of indices grows, so I wonder if there is any better way?
Solution O(I.S.K)
Let's do some naming first:
I is the greatest index (12 in your example)
S is the sum of values whose indices are selected (20 in your example)
K is the number of selected indices
V[] the array of values linked to the indices
maxsum(s, i, k) the maximal sum reachable by using k indices, all differents, whose value is less than or equal to i and whose sum is s.
Then you want to find maxsum(S, I, K)
Your problem exhibits some good properties:
optimal sub-structure
redundant sub-problems
For instance, when trying to compute maxsum(s, i, k) I can either not use index i, in which case the value is maxsum(s, i-1, k). Or I could use index i. In this case, I want to solve the sub-problem: what is the maximum sum reachable by indices less than or equal to i-1 and whose sum is s-i using k-1 such indices. This is the value: V[i] + maxsum(s-i, i-1, k-1).
As we want to reach the maximal sum we end up having: (Edit: corrected maxsum(s-i, i-1, k) to maxsum(s-i, i-1, k-1))
maxsum(s, i, k) = max{ maxsum(s, i-1, k) ; V[i] + maxsum(s-i, i-1, k-1) }
This is typical of a problem solvable by dynamic programming.
Here is an example C++ program solving the problem in O(I.S.K) (space and time).
We can improve the space complexity to O(I.S) at the price of a bigger time complexity: O(I.S.K²).
How to use the program
g++ -std=c++14 -g -Wall -O0 dp.cpp -o dp
./dp input.txt
Where input.txt is a file with the following format:
first line contains three integers: I S K
second line contains I integers, the values of the indices
Example run
---- K=1 ----
17 12 5 22 3 12 6 13 7 0 2 15
[ 1][ 2][ 3][ 4][ 5][ 6][ 7][ 8][ 9][10][11][12]
[ 1] 17 17 17 17 17 17 17 17 17 17 17 17
[ 2] 12 12 12 12 12 12 12 12 12 12 12
[ 3] 5 5 5 5 5 5 5 5 5 5
[ 4] 22 22 22 22 22 22 22 22 22
[ 5] 3 3 3 3 3 3 3 3
[ 6] 12 12 12 12 12 12 12
[ 7] 6 6 6 6 6 6
[ 8] 13 13 13 13 13
[ 9] 7 7 7 7
[10] 0 0 0
[11] 2 2
[12] 15
[13]
[14]
[15]
[16]
[17]
[18]
[19]
[20]
---- K=2 ----
17 12 5 22 3 12 6 13 7 0 2 15
[ 1][ 2][ 3][ 4][ 5][ 6][ 7][ 8][ 9][10][11][12]
[ 1]
[ 2] 12 12 12 12 12 12 12 12 12 12 12
[ 3] 29 29 29 29 29 29 29 29 29 29 29
[ 4] 22 22 22 22 22 22 22 22 22 22
[ 5] 17 39 39 39 39 39 39 39 39 39
[ 6] 34 34 34 34 34 34 34 34 34
[ 7] 27 27 29 29 29 29 29 29 29
[ 8] 8 24 24 24 24 24 24 24
[ 9] 25 25 25 30 30 30 30 30
[10] 34 34 34 34 34 34 34
[11] 15 28 28 28 28 28 28
[12] 9 35 35 35 35 35
[13] 18 18 29 29 29 32
[14] 25 25 25 25 27
[15] 19 19 19 24 24
[16] 13 13 13 37
[17] 20 20 20 20
[18] 13 13 27
[19] 7 15 21
[20] 9 28
---- K=3 ----
17 12 5 22 3 12 6 13 7 0 2 15
[ 1][ 2][ 3][ 4][ 5][ 6][ 7][ 8][ 9][10][11][12]
[ 1]
[ 2]
[ 3]
[ 4]
[ 5] 17 17 17 17 17 17 17 17 17 17
[ 6] 34 34 34 34 34 34 34 34 34 34
[ 7] 51 51 51 51 51 51 51 51 51
[ 8] 44 44 44 44 44 44 44 44 44
[ 9] 39 39 41 41 41 41 41 41 41
[10] 42 42 42 42 42 42 42 42
[11] 37 51 51 51 51 51 51 51
[12] 30 46 46 46 46 46 46 46
[13] 39 40 52 52 52 52 52
[14] 20 35 47 47 47 47 47
[15] 37 37 42 42 42 42 44
[16] 31 37 37 37 41 41
[17] 40 40 40 40 40 54
[18] 21 47 47 47 47 49
[19] 41 41 41 41 44
[20] 22 35 35 35 39
index: 12 sum: 20
index: 6 sum: 8
index: 2 sum: 2
max sum: 39
The source code
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <limits>
#include <valarray>
#include <vector>
using namespace std;
auto const INF = numeric_limits<double>::infinity();
struct matrix {
matrix(size_t rows, size_t cols, double value)
: cells(value, rows*cols)
, rows(rows)
, cols(cols)
, value(value)
{}
double& operator() (int r, int c)
{
if(r < 0 || c < 0)
return value;
return cells[r*cols+c];
}
valarray<double> cells;
size_t rows;
size_t cols;
double value;
};
int main(int argc, char* argv[]) {
if(argc > 1)
freopen(argv[1], "r", stdin);
// I: max index
// S: sum of indices
// K: number of indices in the sum S
int I, S, K;
cin >> I >> S >> K;
// load values
vector<double> V(I+1, 0);
for(int i=1; i<=I; ++i)
cin >> V[i];
// dynamic programming:
// --------------------
// maxsum(i, s, k) is the maximal sum reachable using 'k' indices, less
// than or equal to 'i', all differents, and having a sum of 's'
//
// maxsum(i, s, k) =
// -oo if i > s
//
// -oo if i < s && k == 1
//
// V[s] if i >= s && s <= I && k == 1
// -oo if (i < s || s > I) && k == 1
//
// max { V[i] + maxsum(i-1, S-i, k-1), maxsum(i-1, S, k) }
vector<matrix> maxsum(K+1, matrix(S+1, I+1, -INF));
// initialize K=1
for(int s=0; s<=I && s<=S; ++s) {
for(int i=s; i<=I; ++i) {
maxsum[1](s, i) = V[s];
}
}
// K > 1
for(int k=2; k<=K; ++k) {
for(int s=2; s<=S; ++s) {
for(int i=1; i<=I; ++i) {
auto l = V[i] + maxsum[k-1](s-i, i-1);
auto r = maxsum[k](s, i-1);
maxsum[k](s, i) = max(l, r);
}
}
}
// display the whole dynamic programming tables (optional)
for(int k=1; k<=K; ++k) {
cout << "---- K=" << k << " ----\n";
cout << " ";
for(int i=1; i<=I; ++i) {
cout << setw(3) << V[i] << ' ';
}
cout << '\n';
cout << " ";
for(int i=1; i<=I; ++i) {
cout << '[' << setw(2) << i << ']';
}
cout << '\n';
for(int s=1; s<=S; ++s) {
cout << '[' << setw(2) << s << "] ";
for(int i=1; i<=I; ++i) {
if(maxsum[k](s, i) == -INF) {
cout << " ";
} else {
cout << setw(3) << maxsum[k](s, i) << ' ';
}
}
cout << '\n';
}
}
// output the indices belonging to the solution by working backward in the
// dynamic programming tables
int t_S = S;
int t_I = I;
for(int k=K; k>=1; --k) {
if(t_I <= 0 || t_S <= 0) {
cout << "error...\n";
break;
}
auto m = maxsum[k](t_S, t_I);
int i;
for(i=t_I; i>=1; --i) {
if(maxsum[k](t_S, i) != m)
break;
}
cout << "index: " << setw(3) << (i+1) << ' ';
cout << "sum: " << setw(3) << t_S << '\n';
t_I = i;
t_S = t_S - i - 1;
}
cout << "max sum: " << maxsum[K](S, I) << '\n';
}
Take the arrays, and sort them by value instead of by index (keeping the index-value pairs preserved). Now, starting at the end of the array, take the last k numbers in the indices array, where k is the number of indices you have to have, and sum them up. If it equals the desired sum, great- you are done. If not, take note of the difference (desired sum - actual sum), and add that to the (n - k)th index. Find that index in the index array (ordered by value, mind you), now find your new sum of values (you can optimize this by subtracting out the old index's value and add the new one, instead of recomputing the sum of all k values).
You now have one valid solution, and a lower bound. You know the indices of the rest of the valid solution that can even possibly beat this score must come after the smallest index's value in the value-sorted array. That is:
Both sorted by value-
indices: | bunch of indices | index we found | more | k-1 'random' indices |
values: | bunch of values | value for ^ | more | k-1 largest values |
So we only have to search 'more' and the k-1 largest values for valid indices that satisfy the criteria and also have values that form a larger sum. To do this, we rinse and repeat, moving the smallest of the (n-k-1) elements backwards one, so we effectively try all combination of these elements, but in the order of decreasing subset-sums of our set of k elements. This allows us to continually narrow the space we search as we find larger sums, because know for certain that any sum that contains a smaller value than that of best solution will have a smaller sum (because the rest of the set is already as large as possible).
Pseudo Code:
pair_array = input() // each pair consists of index and value
sort_by_value(pair_array)
best_sum = 0
markers = [n - (k-1) .. n] // mark the k-1 indices being summed
while True:
sum_of_indices = sum_indices(pair_array[markers])
value_sum = sum_value(pair_array[markers])
if pair_array.contains(desired_sum - sum_of_indices): // this lets us effectively reduce our search by a factor of N, given contains uses a hashtable
value_sum += pair_array(pair_array.index(desired_sum - sum_of_indices)).value
if value_sum > best_sum:
best_sum = value_sum
pair_array.remove(0 .. n - (k-1)) // this greatly reduces the combinations checked
if has_next_combination(markers, pair_array):
next_greatest_combination(markers, pair_array) // pick new markers, in a reverse-binary counting fashion (most significant bit first way)
else:
print(best_sum)
break
One small trick I can think if you try to find lets say 3 indexes, is instead of iterating for the 3 indexes you can calculate the 3rd index when you know the first two indexes. For example when you know that
p1 = 1, p2 = 7 => p3 = 20 - (p1 + p2) = 12
This can be generalized when having N indexes the last one can always be inferred from the N-1 previous indexes.
I tried this in Python:
Index = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]
Value = [17, 12, 5, 22, 3, 12, 6, 13, 7, 0, 2, 15 ]
maxSum = 0 SumInd = 20
for p1 in range(1,len(Index)+1):
for p2 in range(p1,len(Index)+1):
if (p1 + p2 < SumInd) and (p1 != p2):
p3 = SumInd - (p1 + p2) #If you know p1 and p2 calculate p3 index
if (p3 < len(Index)+1) and (p2 != p3) and (p1 != p3):
fooSum = Value[p1-1]+Value[p2-1] + Value[p3-1]
print(p1,p2,p3 , "Sum is ",fooSum)
if maxSum < fooSum:
maxSum = fooSum
print("Max Sum is ", maxSum)
Of course you need to save the indexes when you find maxSum. Also this implementation calculate many similar pairs (e.g. [1,9,10] and [9,10,1]). Perhaps a better solution could eliminate this pairs.
EDIT: Big Improvement I found a way to eliminate most unnecessary checks. Let's say you need 3 indexes. The first one checks the whole range of possible values. Let's say it is index1.
The other two indexes must sum at 20 - ind1 let's call this rest. The list of indexes is always ordered so you can have a back index showing the smallest value(first item in the list bigger than index1) and a front index that show the biggest values (last item in the list). So index2 = backIndex , index3 = frontIndex.
If the rest is smaller than the sum of index2,3 you could increase the back index (get the next bigger value) or if it is larger you decrease the front index until the two indexes meet each other where you break and increase index1. This eliminates checking (1,7,12) and (1,12,7) two times.
The code is here in Python:
maxSum = 0
SumInd = 20
for index_1 in range(1,len(Index)):
rest = SumInd - index_1
backIndex = index_1+1
frontIndex = len(Index)
while backIndex < frontIndex:
if rest > (backIndex + frontIndex):
backIndex = backIndex + 1
elif rest < (backIndex + frontIndex):
frontIndex = frontIndex - 1
else:
fooSum = Value[index_1-1]+Value[backIndex-1] + Value[frontIndex-1]
print("Checking for ",index_1,backIndex,frontIndex,' Sum of values:',fooSum)
if maxSum < fooSum:
indList = [index_1-1,backIndex,frontIndex]
maxSum = fooSum
backIndex = backIndex + 1 #To avoid Inf loop
print("Max Sum is ", maxSum,"at",indList)
and gives these results:
Checking for 1 7 12 Sum of values: 38
Checking for 1 8 11 Sum of values: 32
Checking for 1 9 10 Sum of values: 24
Checking for 2 6 12 Sum of values: 39
Checking for 2 7 11 Sum of values: 20
Checking for 2 8 10 Sum of values: 25
Checking for 3 5 12 Sum of values: 23
Checking for 3 6 11 Sum of values: 19
Checking for 3 7 10 Sum of values: 11
Checking for 3 8 9 Sum of values: 25
Checking for 4 5 11 Sum of values: 27
Checking for 4 6 10 Sum of values: 34
Checking for 4 7 9 Sum of values: 35
Checking for 5 6 9 Sum of values: 22
Checking for 5 7 8 Sum of values: 22
Max Sum is 39 at [1, 6, 12]
This can always be generalized for N indexes. The first N-2 indexes can search the whole range of the list (like index 1 in the case above, also it should be noted that all these indexes start checking from previous index value plus one until the end of the list to eliminate many duplicate checks).
The last two indexes can be calculated like I showed in my code and avoid many duplicate checks.

Serialize ternary tree in c

I am writing ternary tree for string lookup in c.
So far I am able to store strings and check whether string exists.
Example insert
Node *node_link(Node *this, char *line) {
26 if(!this) {
27 this = node_create(*line);
28 }
29 if(*line < this->ch) {
30 this->left = node_link(this->left, line);
31 } else if(*line == this->ch) {
32 if(*(++line) == 0) {
33 this->there = TRUE;
34 return this;
35 } else {
36 this->mid = node_link(this->mid, line);
37 }
38 } else {
39 this->right = node_link(this->right, line);
40 }
41 return this;
42 }
I need to get back the strings that I inserted. For example if I inserted
hat
cat
catpost
tent
tents
square
squarish
I should be able to extract the list with same strings. I do not get it if I do tree traversal (DFS). How can I get the list of stored items?
Example traversal
void node_walk_link(Node *this, char *line) {
44 if(this) {
45 node_walk_link(this->left, line);
46 node_walk_link(this->right, line);
47 node_walk_link(this->mid, line_push(line, this->ch, 0));
48 }
49 }
Also how can find union of two ternary trees? That have items from both trees without duplicates.

Travelling Sales Man (need to visit only subset of nodes): Bugged

I need help with my travelling sales man problem code. Its bugged... I know because its a school assignment and there are test cases. So here it goes.
Given a connected graph where I need to visit a subset of nodes. How do I compute the shortest path?
As an example, refer to above image. I need to start from 0 and visit some/all nodes then go back to zero. In the process, I need to compute the shortest path.
Suppose I need to visit all nodes, I will go from 0 -> 1 -> 2 -> 3 -> 0 = 20 + 30 + 12 + 35 = 97. Suppose now I only need to visit node 2, I will go from 0 -> 3 -> 2 -> 3 -> 0 as that gives shortest path of 94 (I can visit nodes I don't have to visit if it can give a shortest path).
Basically, I did:
Compute shortest path between any 2 pairs of required nodes and the source (0). This gives me a shortest path 2D table like (I used dijkstra's):
| 0 1 2 3
--+--------------
0 |
1 |
2 |
3 |
Now, I modify the shopping sales man algorithm (aka. Floyd Warshall’s or APSP) to use this table. Current Java source (TSP and dijkstra's) looks like:
int TSP(int source, int visited) {
if (visited == (int)(Math.pow(2, K)-1)) { // all required visited
return sssp.get(source).get(0); // return to source (0)
} else if (memo.containsKey(source) && memo.get(source).containsKey(visited)) {
return memo.get(source).get(visited);
} else {
int item;
if (!memo.containsKey(source)) {
memo.put(source, new HashMap<Integer, Integer>());
}
memo.get(source).put(visited, 1000000);
for (int v = 0; v < K; v++) {
item = shoppingList[v];
if (!hasVisited(visited, item)) {
memo.get(source).put(visited, Math.min(
memo.get(source).get(visited),
sssp.get(source).get(item) + TSP(item, visit(visited, v))
));
}
}
return memo.get(source).get(visited);
}
}
int dijkstra(int src, int dest) {
PriorityQueue<IntegerPair> PQ = new PriorityQueue<IntegerPair>();
HashMap<Integer, Integer> dist = new HashMap<Integer, Integer>(); // shortest known dist from {src} to {node}
// init shortest known distance
for (int i = 0; i < N+1; i++) {
if (i != src) {
dist.put(i, Integer.MAX_VALUE); // dist to any {i} is big(unknown) by default
} else {
dist.put(src, 0); // dist to {src} is always 0
}
}
IntegerPair node;
int nodeDist;
int nodeIndex;
PQ.offer(new IntegerPair(0, src));
while (PQ.size() > 0) {
node = PQ.poll();
nodeDist = node.first();
nodeIndex = node.second();
if (nodeDist == dist.get(nodeIndex)) {
// process out going edges
for (int v = 0; v < N+1; v++) { // since its a complete graph, process all edges
if (v != nodeIndex) { // except curr node
if (dist.get(v) > dist.get(nodeIndex) + T[nodeIndex][v]) { // relax if possible
dist.put(v, dist.get(nodeIndex) + T[nodeIndex][v]);
PQ.offer(new IntegerPair(dist.get(v), v));
}
}
}
}
}
return dist.get(dest);
}
visited is used as a bitmask to indicate if a node has been visited
sssp is a HashMap<Integer, HashMap<Integer, Integer>> where the 1st hashmap's key is the source node and the key for 2nd hashmap is the destination. So it basically represent the 2D table u see in point 1.
memo is just what I used in dynamic programming as a "cache" of previously computed shortest path from a node, given a visited bitmap.
Full source: http://pastie.org/5171509
The test case that passes:
1
3 3
1 2 3
0 20 51 35
20 0 30 34
51 30 0 12
35 34 12 0
Where 1st line is the number of test cases. 3rd line (3 3). The 1st 3 is the number of nodes, 2nd 3 is the number of required nodes. 4th line is the list of required nodes. Then the rest is the table of edge weights.
The test case that fails is:
9 9
1 2 3 4 5 6 7 8 9
0 42 360 335 188 170 725 479 359 206
42 0 402 377 146 212 767 521 401 248
360 402 0 573 548 190 392 488 490 154
335 377 573 0 293 383 422 717 683 419
188 146 548 293 0 358 715 667 539 394
170 212 190 383 358 0 582 370 300 36
725 767 392 422 715 582 0 880 704 546
479 521 488 717 667 370 880 0 323 334
359 401 490 683 539 300 704 323 0 336
206 248 154 419 394 36 546 334 336 0
I got 3995 but the answer is 2537... sorry I know this is hard to debug ... I am having the same problem, the test case is too large ... at least for humans ... so I am creating smaller test case to test but they seem to pass ...
Perhaps not a full answer but I think it's at least pointing in the right direction: your code seems to give the results of following the paths 0->1->2->...->N->0. No real optimization seems to happen.
I reworked your code a bit to get a small failing test case:
int[][]mat=new int[N+1][N+1];
//original
//mat[0]=new int[]{0,20,51,35};
//mat[1]=new int[]{20,0,30,34};
//mat[2]=new int[]{51,30,0,12};
//mat[3]=new int[]{35,34,12,0};
//switched order of nodes, node 2 is now node 1
mat[0]=new int[]{0,51,20,35};
mat[1]=new int[]{51,0,30,12};
mat[2]=new int[]{20,30,0,34};
mat[3]=new int[]{35,12,34,0};
This produces 146 as a best path, showing that it follows the path 0->1->2->3->0 (47+30+34+35, 47 is the shortest path 0 to 1 using node 4) (all node numbers are with my order switch).
edit: I found the culprit after another quick look. You have the line if (!hasVisited(visited, item)) to check if you already visited node item. However, visited is built up by visit(visited, v), in which v is an index into the shoppinglist. item =shoppinglist[v] but you should use the same if you're shifting your visited vector.
You should use if (!hasVisited(visited, v)) instead of if (!hasVisited(visited, item))
On an unrelated note, I'm unsure if the first step of finding the shortest paths is necessary or could influence your results. If a direct link from A to B is longer than going through other nodes (say C), then it is replaced in the distance table. If you would then use that link in your final solution to go from A to B, then you would actually be going via C, which would already be in your path (since that path is a full TSP solution). If a node can only be visited once, then this might be a problem.

Resources