Forming a circle/chain from set of string pairs C++ - algorithm

So, I have an assignment to do in C++, but I can't figure out how to :/
I have to use backtracking, which is completely alien to me.
The problem:
You are given n number of people with their names and m number of relations(friends) between them. Each relation consists of two names, forming a pair of strings. Everyone has at least n/2 friends. The first person has a book which he lends to one of his friends.
The book has to "travel" through everyone and end up in the hands of the first person.
Write out every possible solution.
The input should contain a number for n followed by a number for m followed by m number of rows each containing a relation.
Something like this:
The input...
3 3
Matt Susy
Matt Alan
Susy Alan
...would result in:
Matt Susy Alan Matt
Matt Alan Susy Matt
and so on for more people.
I have been banging my head against the table because no matter what I do, I can't figure it out :/
As I said, this is a relatively new concept for me and every little help would be appreciated :)
The thing is that this code works, but I can't submit it, because the teacher said that someone already approached this problem using this method, so I have to come up with a different solution for it. (Believe it or not, this has happened too many times already...) The base idea can have some resemblance to this one, but a different approach would be better.
Please forgive the names of the variables, english is not my first language so I wrote it using words from my language :)
#include<iostream>
#include<fstream>
using namespace std;
void input_1D(string nev_1D[])
{
ifstream be("skam0286_L6_9.txt");
int x, i, j, k=1, ok;
string akt;
be>>x>>x;
for(i=0; i<2*x; ++i)
{
be>>akt;
for(j=1, ok=1; j<=k; ++j) if(nev_1D[j]==akt) ok=0;
if(ok) nev_1D[k++]=akt;
}
be.close();
}
void input_2D(int &n, int &m, string nev_2D[][3])
{
int i;
ifstream be("skam0286_L6_9.txt");
be>>n>>m;
for(i=1;i<=m;++i) be>>nev_2D[i][1]>>nev_2D[i][2];
be.close();
}
void output(int n, string eredm[])
{
int i;
for(i=1;i<=n;i++) cout<<eredm[i]<<" ";
cout<<endl;
}
bool helyes(int n, string akt, string eredm[])
{
int i, ok=0;
for(i=1; i<n && !ok; ++i)
if(eredm[i]==akt) ok=1;
return ok;
}
bool barat(int m, string nev_2D[][3], string n1, string n2)
{
int i, ok=0;
for(i=1;i<=m && !ok; ++i)
if((n1==nev_2D[i][1] && n2==nev_2D[i][2])||(n1==nev_2D[i][2] && n2==nev_2D[i][1]))
ok=1;
return ok;
}
void bt(int n, int m, string nev_2D[][3], string nev_1D[], string eredm[], int ind)
{
if(ind==n+1){
if(barat(m, nev_2D, eredm[1], eredm[ind-1])){
eredm[ind]=eredm[1];
output(ind, eredm);
}
}
else{
int i;
for(i=1; i<=n; ++i)
if(!helyes(ind, nev_1D[i], eredm) && barat(m, nev_2D, eredm[ind-1], nev_1D[i])){
eredm[ind]=nev_1D[i];
bt(n, m, nev_2D, nev_1D, eredm, ind+1);
}
}
}
int main()
{
int n, m;
string nev_2D[100][3], nev_1D[100], eredm[100];
eredm[1]="Matt";
input_2D(n,m,nev_2D);
input_1D(nev_1D);
bt(n, m, nev_2D, nev_1D, eredm, 2);
return 0;
}

Related

I have algorithm for finding maximum flow. Does it have an author or name?

I'm beginner in programming and I'm learning algorithms to find maximum flows.
Most of them are rather difficult such as Ford-Falkerson, Edmunds-Karp and Dinitz. The problem is here: https://cses.fi/problemset/task/1694
I found an algorithm that finds maximum flow just for one depth first search for O(n+m). What is the name or author of this algorithm? This solution uses just one DFS. All standard algorithms use many DFS or BFS searches, but not this. I'm a bit confused.
#include<bits/stdc++.h>
using namespace std;
vector<vector<pair<int, long long>>> adj;
vector<bool> visited;
long long dfs(int to) {
long long r = 0;
visited[to] = true;
for (const auto& [from, flow]: adj[to]) {
if (from == 1 || visited[from]) {
r += flow;
} else {
r += min(flow, dfs(from));
}
}
return r;
}
int main() {
int n, m;
cin >> n >> m;
adj.resize(n + 1);
visited.resize(n + 1, false);
for (int i = 0; i < m; i++) {
int from, to, flow;
cin >> from >> to >> flow;
adj[to].push_back({from, flow});
}
cout << dfs(n);
}
Can you help me to understand why Dinitz or Edmunds-Karp, with O(m2n) complexity, are needed?
Breaks on the following graph since the second visit to v will incorrectly assume that there is one unit of flow available to pull:

Count of subsetsum problem, how to debug where the solution is not working?

So I'm trying to solve this problem :
Given an array arr[] of integers and an integer sum, the task is to
count all subsets of the given array with a sum equal to a given sum.
Note: Answer can be very large, so, output answer modulo 10^9+7
Now this is the solution I'm trying out here:
class Solution{
private:
vector<vector<int>> t;
public:
Solution() {
t.resize(1001, vector<int> (1001,-1));
}
int perfectSum(int arr[], int n, int sum)
{
long long int result = fmod(sumrecursive(arr, n, sum),(pow(10,9)+7));
return result;
}
long long int sumrecursive(int arr[], int n, int sum){
if(sum==0){
return 1;
}
if(n==0){
return 0;
}
if(t[n][sum] != -1){
return t[n][sum];
}
if(arr[n-1]>sum){
return t[n][sum] = sumrecursive(arr, n-1, sum);
} else {
return t[n][sum] = sumrecursive(arr,n-1, sum-arr[n-1]) + sumrecursive(arr, n-1, sum);
}
}
};
Now this code is not working after some certain input:
I don't know on how to proceed in solving this problem at this point. Ideally according to the code I have written the input is within the grasp of the code and output should've been correct but unfortunately it is not the case. I wanted to ask if someone could spot on where the problem might be in the code or guide me on how to debug where the problem is in the code.
You are probably encountering integer overflow along the way.
You are taking the mod only right before ending the function, but your cache is of type int, so when placing too big numbers - you are losing some data due to overflow.

bipartite matching in C++, what is wrong in my code?

I have worked on a bipartite matching problem, and I obviously got a trouble to solve it.
Let me tell you what the problem is about.
As an input form, it gives me N, M which is the number of people at the work and the number of different kind of jobs in the work.
In the following N lines, it tells us s that tells how many kind of job that ith person can do. In the following s numbers, they will tell us that which jobs can ith person can do. The number of the jobs si will satisfy 1<=si<=M.
Then, if each person can work on only one or less job at a time, how many jobs can be done at most?
This is the problem, and I hope this made sense for you;) I apologize my poor english skill. Returning to the point, this is my code.
#include <stdio.h>
int n, m, dfscheck[1003], check[1003], input[1003][1003], back[1003], tmp, count=0;
void dfs(int num)
{
int i, j;
if(check[num]==0)
{
tmp=-1;
check[num]=1;
return;
}
if(dfscheck[num]==1)
return;
dfscheck[num]=1;
for(j=1; j<=input[back[num]][0]; j++)
{
dfs(input[back[num]][j]);
if(tmp==-1)
{
back[input[back[num]][j]]=back[num];
return;
}
}
}
int main(void)
{
int i, j, flag ,k;
scanf("%d %d", &n, &m);
for(i=1; i<=n; i++)
{
scanf("%d", &input[i][0]);
for(j=1; j<=input[i][0]; j++)
scanf("%d", &input[i][j]);
}
for(i=1; i<=n; i++)
{
flag=0;
for(j=1; j<=input[i][0]; j++)
if(check[input[i][j]]==0)
{
check[input[i][j]]=1;
count++;
flag=1;
back[input[i][j]]=i;
break;
}
if(flag==0)
for(j=1; j<=input[i][0]; j++)
{
for(k=0; k<=1001; k++)
dfscheck[k]=0;
tmp=0;
dfs(input[i][j]);
if(tmp==-1)
{
back[input[i][j]]=i;
count++;
}
}
}
printf("%d", count);
return 0;
}
The name of tmp is really bad to understand code, so... tmp works like a flag in the function dfs. It tells whether it has found a matching.
I got wrong answer, neither runtime error nor time exceed. I have read several different codes that others have written, and I couldn't find which part is wrong in my code.
I have found that my code is distinct from others' in the part that I don't define a array, A[i], showing which job is matched to ith person, exactly opposite to Back array in my code. As far as I understood their codes, the purpose of it is to find out ith person has already been matched before we get into dfs. I don't think this case can be happened. Since no flow has come out of the node of ith person, it is impossible for a flow to go from a node of jobs to the node in max flow.
I wanted to say my thoughts even if it is useless, just in case that it helps you give me some advices. Anyway, let me have your opinions!!!
Thank you so much for your time.
One thing that looks weird is:
if(tmp==-1)
{
back[input[i][j]]=i;
count++;
// I would expect to see "break;" here
}
if you find a way to assign person i to a job you increment the count, and then carry on trying to see if you can find an alternative way to assign the same person. This means that you may end up assigning the same person to multiple jobs!
I recommend inserting a "break;" statement once you have found a job for the person.

Find word in string buffer/paragraph/text

This was asked in Amazon telephonic interview - "Can you write a program (in your preferred language C/C++/etc.) to find a given word in a string buffer of big size ? i.e. number of occurrences "
I am still looking for perfect answer which I should have given to the interviewer.. I tried to write a linear search (char by char comparison) and obviously I was rejected.
Given a 40-45 min time for a telephonic interview, what was the perfect algorithm he/she was looking for ???
The KMP Algorithm is a popular string matching algorithm.
KMP Algorithm
Checking char by char is inefficient. If the string has 1000 characters and the keyword has 100 characters, you don't want to perform unnecessary comparisons. The KMP Algorithm handles many cases which can occur, but I imagine the interviewer was looking for the case where: When you begin (pass 1), the first 99 characters match, but the 100th character doesn't match. Now, for pass 2, instead of performing the entire comparison from character 2, you have enough information to deduce where the next possible match can begin.
// C program for implementation of KMP pattern searching
// algorithm
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void computeLPSArray(char *pat, int M, int *lps);
void KMPSearch(char *pat, char *txt)
{
int M = strlen(pat);
int N = strlen(txt);
// create lps[] that will hold the longest prefix suffix
// values for pattern
int *lps = (int *)malloc(sizeof(int)*M);
int j = 0; // index for pat[]
// Preprocess the pattern (calculate lps[] array)
computeLPSArray(pat, M, lps);
int i = 0; // index for txt[]
while (i < N)
{
if (pat[j] == txt[i])
{
j++;
i++;
}
if (j == M)
{
printf("Found pattern at index %d \n", i-j);
j = lps[j-1];
}
// mismatch after j matches
else if (i < N && pat[j] != txt[i])
{
// Do not match lps[0..lps[j-1]] characters,
// they will match anyway
if (j != 0)
j = lps[j-1];
else
i = i+1;
}
}
free(lps); // to avoid memory leak
}
void computeLPSArray(char *pat, int M, int *lps)
{
int len = 0; // length of the previous longest prefix suffix
int i;
lps[0] = 0; // lps[0] is always 0
i = 1;
// the loop calculates lps[i] for i = 1 to M-1
while (i < M)
{
if (pat[i] == pat[len])
{
len++;
lps[i] = len;
i++;
}
else // (pat[i] != pat[len])
{
if (len != 0)
{
// This is tricky. Consider the example
// AAACAAAA and i = 7.
len = lps[len-1];
// Also, note that we do not increment i here
}
else // if (len == 0)
{
lps[i] = 0;
i++;
}
}
}
}
// Driver program to test above function
int main()
{
char *txt = "ABABDABACDABABCABAB";
char *pat = "ABABCABAB";
KMPSearch(pat, txt);
return 0;
}
This code is taken from a really good site that teaches algorithms:
Geeks for Geeks KMP
Amazon and companies alike expect knowledge of Boyer–Moore string search or / and Knuth–Morris–Pratt algorithms.
Those are good if you want to show perfect knowledge. Otherwise, try to be creative and write something relatively elegant and efficient.
Did you ask about delimiters before you wrote anything? It could be that they may simplify your task to provide some extra information about a string buffer.
Even code below could be ok (it's really not) if you provide enough information in advance, properly explain runtime, space requirements, choice of data containers.
int find( std::string & the_word, std::string & text )
{
std::stringstream ss( text ); // !!! could be really bad idea if 'text' is really big
std::string word;
std::unordered_map< std::string, int > umap;
while( ss >> text ) ++umap[text]; // you have to assume that each word separated by white-spaces.
return umap[the_word];
}

My code for merge sort in C++ using dynamic arrays returning garbage values

Please tell me why this code is giving garbage values
Compiles well, implemented this based on the Cormen algorithm for mergesorting
Basically taking given numbers in a dynamic array. two void functions are taken.One is to merge the two sub arrays via merge sort and the other to recursively split the array to sub arrays
#include<iostream>
using namespace std;
void merge(int *A,int p, int q, int r)// a function to merge two //sub arrays
{
int n1= q-p+1;
int n2=r-q;
int L[n1];
int R[n2];
for (int i=0;i<n1;i++)
{
L[i]=A[p+i];
}
int m=1;
for(int j=0; j<n2 ;j++)
{
R[j]=A[q+m];
m=m+1;
}
int i=0;
int j=0;
for(int k=0;k<r;k++)
{
if (L[i]<=R[j])
{
A[k]=L[i];
i=i+1;
}
else
{
A[k]=R[j];
j=j+1;
}
}
}
void mergesort(int *A,int p,int r)// dividng the sequence to sub arrays
{
if (p<r)
{
int q;
q=(p+r)/2;
mergesort(A,p,q);
mergesort(A,(q+1),r);
merge(A,p,q,r);
}
}
int main()
{
int n;
cout<<"Enter the number of numbers to be sorted by merge sort"<<endl;
cin>>n;
int* a=NULL;
a=new int[n];
int temp;
cout<<"Enter the numbers"<<endl;
for(int i=0;i<n;i++)
{
cin>>temp;
*(a+i)=temp;// inputting the given numbers into a dynamic array
}
cout<<"The given numbers are:"<<endl;
for(int j=0;j<n;j++)
cout<<*(a+j)<<" ";
mergesort(a,0,n-1);
cout<<"The merged sorted numbers are:"<<endl;
for(int s=0;s<n;s++)
cout<<*(a+s)<<" ";
delete [] a;
system("pause");
return 0;
}
You are getting your intervals wrong pretty much everywhere in your code. For example:
Based on your usage in main, mergesort is supposed to sort the sublist of indices [0,n-1].
With this meaning, your recursion in mergesort says in order to sort the indices [p,r-1], you should first sort [p,q-1] then sort [q+1,r-1]: you completely ignore index q.
Similarly, merge is confused: once you fix the typo when coping into L (A[i] should be A[p+i]), it takes [p,q] as one list, and [q,r] as the other list: note you copy entry q twice, and you also copy r when you probably shouldn't be.
To fix your code, you need to straighten out exactly what intervals everything is supposed to be working on. This isn't a hard problem, you just have to bring yourself to write down explicitly exactly what all of your functions and loops and stuff are supposed to be doing.
The typical convention these days is half-open intervals: you should generally think of taking indices [p,q) from a list. ([p,q) is the same as [p,q-1]) Here are several examples of why this is preferred:
The number of entries of [p,r) is simply r-p
A for loop iterating through [p,r) is the usual for(i=p; i<r; ++i) (not <=)
Splitting the interval [p,r) into parts gives you intervals [p,q) and [q,r) -- there is no worry about remembering to add 1 in places.
e.g. merge would normally be designed to take the first list comes from indices [p,q) and the second list from indices [q,r).

Resources