I am writing Djikstra's algorithm in C++, and am having trouble getting the code to print anything other than the path from A->A. I need to get it to find the path from A->X where X is any one of the nodes A-I.
Expected Output
Actual Output
#include <climits>
#include <fstream>
#include <iostream>
using namespace std;
const int V = 9;
// Function to print shortest path from source to j
// using parent array
void printPath(int parent[], int j) {
char str = j;
// Base Case : If j is source
if (parent[j] == -1) {
cout << str << " ";
return;
}
printPath(parent, parent[j]);
// printf("%d ", j);
cout << str << " ";
}
int miniDist(int distance[], bool Tset[]) // finding minimum distance
{
int minimum = INT_MAX, ind;
for (int k = 0; k < V; k++) {
if (Tset[k] == false && distance[k] <= minimum) {
minimum = distance[k];
ind = k;
}
}
return ind;
}
void DijkstraAlgo(int graph[V][V], char sourceNode,
char endNode) // adjacency matrix
{
int distance[V]; // array to calculate the minimum distance for each node
bool Tset[V]; // boolean array to mark visited and unvisited for each node
int parent[V]; // Parent array to store shortest path tree
// Value of parent[v] for a vertex v stores parent vertex of v
// in shortest path tree.
for (int k = 0; k < V; k++) {
distance[k] = INT_MAX;
Tset[k] = false;
}
parent[sourceNode] = -1; // Parent of root (or source vertex) is -1.
distance[sourceNode] = 0; // Source vertex distance is set 0
for (int k = 0; k < V; k++) {
int end = miniDist(distance, Tset);
Tset[end] = true;
for (int k = 0; k < V; k++) {
// updating the distance of neighbouring vertex
if (!Tset[k] && graph[end][k] && distance[end] != INT_MAX &&
distance[end] + graph[end][k] < distance[k]) {
distance[k] = distance[end] + graph[end][k];
parent[k] = end;
}
}
}
cout << "Vertex\t\tDistance from source vertex\t\t Path" << endl;
int k = sourceNode;
char str = k;
// cout<<str<<"\t\t\t"<<distance[k]<<endl;
cout << str << "\t\t\t" << distance[k] << "\t\t\t\t\t\t\t\t";
printPath(parent, k);
cout << endl;
}
int main() {
char choice1, choice2;
ifstream inFile;
inFile.open("graph.txt");
int graph[V][V];
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++)
inFile >> graph[i][j];
}
cout << "Nodes: "
<< "A, B, C, D, E, F, G, H, I" << endl;
cout << "Enter starting node: ";
cin >> choice1;
cout << "Enter ending node: ";
cin >> choice2;
cout << endl;
DijkstraAlgo(graph, choice1, choice2);
inFile.close();
return 0;
}
So, I have to be able to pass the endNode parameter to something somehow, correct?
The main issue lies here:
int miniDist(int distance[], bool Tset[])
In your minimum distance calculation, you don't exclude the source vertex. All other vertices have INT_MAX distance and the source has 0 distance, so it gets picked. Try going through the algorithm once again to fix your implementation.
Related
Here's the link for the problem:
I have used union-find algorithm to solve the problem.
Code:
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
#define INT 100000000
unordered_map<ll, ll> parent;
unordered_map<ll, ll> depth;
std::vector<ll> cost;
ll find_set(ll x) {
if (x == parent[x])return x;
parent[x] = find_set(parent[x]);
return parent[x];
}
void union_set(ll x, ll y) {
/*
Creating a disjoint set such that the node with smallest cost
being the root using union-rank concept.
*/
ll rep1 = find_set(x), rep2 = find_set(y);
if (depth[rep1] > depth[rep2])parent[rep1] = rep2;
else if (depth[rep2] >= depth[rep1])parent[rep2] = rep1;
}
int main() {
ll n, m;
cin >> n >> m;
ll c[m + 1][3];
for (ll i = 1; i <= m; i++) {
cin >> c[i][1] >> c[i][2]; //Accepting the edges
}
for (ll i = 1; i <= n; i++) {
parent[i] = i;
cin >> depth[i];
if (depth[i] < 0)depth[i] = INT;
/*we assume that each negative cost is replaced by a very
large positive cost.*/
}
for (ll i = 1; i <= m; i++) {
union_set(c[i][1], c[i][2]);
}
set<ll> s;
std::vector<ll> v;
//storing representatives of each connected component
for (auto i = 1; i <= n; i++)s.insert(depth[find_set(i)]);
for (auto it = s.begin(); it != s.end(); it++)v.push_back(*it);
sort(v.begin(), v.end());
if (s.size() == 1) {
//Graph is connected if there is only 1 connected comp
cout << 0 << endl;
return 0;
}
bool flag = false;
ll p = 0;
for (ll i = 1; i < v.size(); i++) {
if (v[i] == INT) {
flag = true;
break;
}
p += (v[0]+v[i]);
}
if (flag)cout << -1 << endl;
else cout << p << endl;
return 0;
}
Logic used in my program:
To find the answer, take the minimum value of all the valid values in a connected component.Now to make the graph connected, Take the minimum value of all the values we got from the above step and make edge from that node to all the remaining nodes.If graph is already connected than answer is 0.if there exists a connected component where all nodes are not valid to be chosen, than answer is not possible (-1).
But this solution is not accepted?What's wrong with it?
I've found an implementation of famous welsh Powell algorithm code in c++, and just to check it's working I compiled the code and executed it. unfortunately, it's giving me a segmentation fault and I'm not able to figure this out. Any helps would be highly appreciated.
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
// A class that represents an undirected graph
class Graph
{
int V; // No. of vertices
list<int> *adj; // A dynamic array of adjacency lists
public:
// Constructor and destructor
Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
~Graph()
{
delete [] adj;
}
// function to add an edge to graph
void addEdge(int v, int w);
// Prints greedy coloring of the vertices
void greedyColoring();
};
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w);
adj[w].push_back(v); // Note: the graph is undirected
}
struct vertexDegree
{
int v;
int degree;
};
bool compareByDegree(const vertexDegree& x, const vertexDegree& y)
{
return x.degree > y.degree;
}
// Assigns colors (starting from 0) to all vertices and prints
// the assignment of colors
void Graph::greedyColoring()
{
int result[V];
// Initialize remaining V-1 vertices as unassigned
for (int u = 1; u < V; u++)
result[u] = -1; // no color is assigned to u
// A temporary array to store the available colors. True
// value of available[cr] would mean that the color cr is
// assigned to one of its adjacent vertices
bool available[V];
for (int cr = 0; cr < V; cr++)
available[cr] = false;
vertexDegree arr[V];
for (int i = 0; i < V; i++)
{
arr[i].v = i;
arr[i].degree = adj[i].size();
}
sort(arr, arr+V, compareByDegree);
cout << "Sorted vertices \n";
for (int i = 0; i <V; i++)
{
cout << arr[i].v << " ";
}
cout << "\n";
// Assign the first color to first vertex in sorted array
result[arr[0].v] = 0;
// Assign colors to remaining V-1 vertices
for (int x = 1; x < V; x++)
{
int u = arr[x].v;
// Process all adjacent vertices and flag their colors
// as unavailable
list<int>::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
if (result[*i] != -1)
available[result[*i]] = true;
// Find the first available color
int cr;
for (cr = 0; cr < V; cr++)
if (available[cr] == false)
break;
result[u] = cr; // Assign the found color
// Reset the values back to false for the next iteration
for (i = adj[u].begin(); i != adj[u].end(); ++i)
if (result[*i] != -1)
available[result[*i]] = false;
}
// print the result
for (int u = 0; u < V; u++)
cout << "Vertex " << u << " ---> Color "
<< result[u] << endl;
}
// Driver program to test above function
int main()
{
Graph g1(5);
g1.addEdge(0, 1);
g1.addEdge(0, 2);
g1.addEdge(1, 2);
g1.addEdge(1, 3);
g1.addEdge(2, 3);
g1.addEdge(3, 4);
cout << "Coloring of Graph 1 \n";
g1.greedyColoring();
Graph g2(5);
g2.addEdge(0, 1);
g2.addEdge(0, 2);
g2.addEdge(1, 2);
g2.addEdge(1, 4);
g2.addEdge(2, 4);
g2.addEdge(4, 3);
cout << "\nColoring of Graph 2 \n";
g2.greedyColoring();
return 0;
}
competitive programming noob here. I've been trying to solve this question:
http://www.usaco.org/index.php?page=viewproblem2&cpid=646
The code I wrote only works with the first test case, and gives a Memory Limit Exceed error -- or ('!') for the rest of the test cases.
This is my code (accidently mixed up M and N):
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
using std::vector;
vector<int> check;
vector< vector<int> > A;
void dfs(int node)
{
check[node] = 1;
int siz = A[node].size();
for (int i = 0; i < siz; i++)
{
int y = A[node][i];
if (check[y] == 0)
{
dfs(y);
}
}
}
bool connected(vector<int> C)
{
for (int i = 1; i <= C.size() - 1; i++)
{
if (C[i] == 0)
{
return false;
}
}
return true;
}
int main()
{
freopen("closing.in", "r", stdin);
freopen("closing.out", "w", stdout);
ios_base::sync_with_stdio(false);
int M, N;
cin >> M >> N;
check.resize(M + 1);
A.resize(M + 1);
for (int i = 0; i < N; i++)
{
int u, v;
cin >> u >> v;
A[u].push_back(v); A[v].push_back(u);
}
dfs(1);
if (!connected(check)) {
cout << "NO" << "\n";
}
else {
cout << "YES" << "\n";
}
fill(check.begin(), check.end(), 0);
for (int j = 1; j < M; j++)
{
int node;
bool con = true;
cin >> node;
check[node] = -1;
for (int x = 1; x <= N; x++)
{
if (check[x] == 0)
{
dfs(x);
break;
}
}
if (!connected(check)) {
cout << "NO" << "\n";
}
else {
cout << "YES" << "\n";
}
for (int g = 1; g <= M; g++)
{
if (check[g] == 1)
{
check[g] = 0;
}
}
}
return 0;
}
basically,
void dfs(int node) searches through the bidirectional graph starting from node until it reaches a dead end, and for each node that is visited, check[node] will become 1.
(if visited -> 1, not visited -> 0, turned off -> -1).
bool connected(vector C) will take the check vector and see if there are any nodes that weren't visited. if this function returns true, it means that the graph is connected, and false if otherwise.
In the main function,
1) I save the bidirectional graph given in the task as an Adjacency list.
2) dfs through it first to see if the graph is initially connected (then print "Yes" or "NO") then reset check
3) from 1 to M, I take the input value of which barn would be closed, check[the input value] = -1, and dfs through it. After that, I reset the check vector, but keeping the -1 values so that those barns would be unavailable for the next loops of dfs.
I guess my algorithm makes sense, but why would this give an MLE, and how could I improve my solution? I really can't figure out why my code is giving MLEs.
Thanks so much!
Your DFS is taking huge load of stacks and thus causing MLE
Try to implement it with BFS which uses queue. Try to keep the queue as global rather than local.
Your approach will give you Time Limit Exceeded verdict. Try to solve it more efficiently. Say O(n).
Let's say I have a graph like this
I want to find all the edges from 1 to 3 i.e. 1 2... 2 4... 4 3. I can write the code for 1 to 5 quite easily but when the next node in descending order then my code doesn't work. Please help me with that.
Here is my code:-
given if there is edge between i and j then:-
arr[i][j]=0
where s is total number of nodes and i have to find edges between a and b
for(int i=a;i!=b;)
{
for(int j=1;j<=s;j++)
{
if(arr[i][j]==0)
{
//cout<<i<<" "<<j<<endl;
i=j;
}
}
}
This can be solved using Breadth first search algorithm we can keep track of the parent of the current node while performing a BFS, and then can construct the path from that if the path exists, i have written a c++ solution below
#include<iostream>
#include<queue>
using namespace std;
int n, arr[100][100], par[100], vis[100], ans[100];
void bfs(int start, int end){
queue<int> Q;
Q.push(start);
par[start] = -1;vis[start] = 1;
bool found = false;
while(Q.size() > 0){
int v = Q.front();
Q.pop();
if(v == end){
found = true;
break;
}
for(int i = 1;i <= n;i++){
if(arr[v][i] == 0 || vis[i] == 1) continue;
Q.push(i);vis[i] = 1;
par[i] = v;
}
}
if(found == false){
cout << "No Path Found" << endl;return;
}
int curr = end, len = 0;
while(curr != -1){
ans[len++] = curr;
curr = par[curr];
}
for(int i = len-1;i >= 1;i--) cout << ans[i] << " " << ans[i-1] << endl;
}
int main(){
n = 5;
arr[1][2] = 1;arr[2][1] = 1;
arr[2][4] = 1;arr[4][2] = 1;
arr[4][5] = 1;arr[5][4] = 1;
arr[3][4] = 1;arr[4][3] = 1;
bfs(1, 3);
return 0;
}
Link to solution on Ideone : http://ideone.com/X8QnNu
I am trying to solve this problem, I think I have come up with a correct answer, but I am keep getting WA (wrong answer) response from the judge.
http://www.spoj.com/problems/FISHER/
The problem distilled, is, given a complete graph with a time and a toll associated with each edge, find a path from the first node to the last node within time constraint and minimize toll.
As with any problems, there are many ways to solve it. My idea is to extend the Floyd-Warshall algorithm to keep track of all non-dominated paths. At the end of the algorithm, we extract the path with minimal cost, and if there are multiple paths with the same cost, choose the one that spent least time.
Complexity aside, the bad thing is, wrong answer. I have no idea what is wrong. I have generated some random graphs and used a brute force solver (one that try all possible paths) and they matches exactly on small (i.e. less than 11 nodes) graphs. Without further ado, here is the code:
#include "stdafx.h"
// http://www.spoj.com/problems/FISHER/
// #define LOG
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
int main()
{
while (true)
{
int num_cities;
int time_budget;
vector<vector<int> > distances;
vector<vector<int> > tolls;
cin >> num_cities;
cin >> time_budget;
if (num_cities == 0 && time_budget == 0)
{
break;
}
distances.resize(num_cities);
tolls.resize(num_cities);
for (int i = 0; i < num_cities; i++)
{
distances[i].resize(num_cities);
tolls[i].resize(num_cities);
}
for (int i = 0; i < num_cities; i++)
{
for (int j = 0; j < num_cities; j++)
{
int distance;
cin >> distance;
distances[i][j] = distance;
}
}
for (int i = 0; i < num_cities; i++)
{
for (int j = 0; j < num_cities; j++)
{
int toll;
cin >> toll;
tolls[i][j] = toll;
}
}
// Try Floyd Warshall
// Denote the set of shortest paths from i to j going through {0,1,...k - 1} be shortest_paths[i][j][k],
// It is a set of shortest paths because there can be multiple shortest paths with different time used.
// We should record if using longer time can lead to lower cost, or similarly higher cost but less time
// The first element in the pair is the cost, the second element in the pair is time used
vector<vector<vector<vector<pair<int, int> > > > > shortest_paths;
shortest_paths.resize(num_cities);
for (int i = 0; i < num_cities; i++)
{
shortest_paths[i].resize(num_cities);
for (int j = 0; j < num_cities; j++)
{
shortest_paths[i][j].resize(num_cities + 1);
}
}
// Initialization - there is only one path without going through any node
#ifdef LOG
cout << "k = " << 0 << endl;
cout << "<table border='1'>" << endl;
#endif
for (int i = 0; i < num_cities; i++)
{
#ifdef LOG
cout << "<tr>" << endl;
#endif
for (int j = 0; j < num_cities; j++)
{
#ifdef LOG
cout << "<td>(" << tolls[i][j] << ", " << distances[i][j] << ")</td>";
#endif
shortest_paths[i][j][0].push_back(pair<int, int>(tolls[i][j], distances[i][j]));
}
#ifdef LOG
cout << "</tr>" << endl;
#endif
}
#ifdef LOG
cout << "</table>" << endl;
#endif
// Iteration - the shortest path
for (int k = 1; k <= num_cities; k++)
{
#ifdef LOG
cout << "k = " << k << endl;
cout << "<table border='1'>" << endl;
#endif
for (int i = 0; i < num_cities; i++)
{
#ifdef LOG
cout << "<tr>";
#endif
for (int j = 0; j < num_cities; j++)
{
// Step 1: Generate all candidate shortest paths
map<pair<int, int>, bool> candidates;
for (vector<pair<int, int> >::iterator pi = shortest_paths[i][j][k - 1].begin(); pi != shortest_paths[i][j][k - 1].end(); pi++)
{
candidates.insert(pair<pair<int, int>, bool>(*pi, false));
}
for (vector<pair<int, int> >::iterator fi = shortest_paths[i][k - 1][k - 1].begin(); fi != shortest_paths[i][k - 1][k - 1].end(); fi++)
{
for (vector<pair<int, int> >::iterator si = shortest_paths[k - 1][j][k - 1].begin(); si != shortest_paths[k - 1][j][k - 1].end(); si++)
{
int first_path_cost = fi->first;
int first_path_time_used = fi->second;
int second_path_cost = si->first;
int second_path_time_used = si->second;
int new_path_cost = first_path_cost + second_path_cost;
int new_path_time_used = first_path_time_used + second_path_time_used;
if (new_path_time_used <= time_budget)
{
candidates.insert(pair<pair<int, int>, bool>(pair<int, int>(new_path_cost, new_path_time_used), false));
}
}
}
vector<pair<pair<int, int>, bool> > candidates_list;
for (map<pair<int,int>, bool>::iterator ci = candidates.begin(); ci != candidates.end(); ci++)
{
candidates_list.push_back(*ci);
}
// Eliminate the bad ones
for (unsigned int p = 0; p < candidates_list.size(); p++)
{
for (unsigned int q = 0; q < candidates_list.size(); q++)
{
if (p != q)
{
int first_path_cost = candidates_list[p].first.first;
int first_path_time_used = candidates_list[p].first.second;
int second_path_cost = candidates_list[q].first.first;
int second_path_time_used = candidates_list[q].first.second;
// First take less time and less cost than second, second is eliminated
if (first_path_time_used <= second_path_time_used && first_path_cost <= second_path_cost)
{
candidates_list[q].second = true;
}
}
}
}
#ifdef LOG
cout << "<td>";
#endif
for (unsigned int p = 0; p < candidates_list.size(); p++)
{
if (candidates_list[p].second == false)
{
#ifdef LOG
cout << "(" << candidates_list[p].first.first << ", " << candidates_list[p].first.second << ")<br>";
#endif
shortest_paths[i][j][k].push_back(candidates_list[p].first);
}
}
#ifdef LOG
cout << "</td>";
#endif
}
#ifdef LOG
cout << "</tr>" << endl;;
#endif
}
#ifdef LOG
cout << "</table>" << endl;
#endif
}
bool first = true;
int best_cost = -1;
int best_cost_time = -1;
for (vector<pair<int, int> >::iterator pi = shortest_paths[0][num_cities - 1][num_cities].begin(); pi != shortest_paths[0][num_cities - 1][num_cities].end(); pi++)
{
if (first)
{
best_cost = pi->first;
best_cost_time = pi->second;
first = false;
}
else
{
if (pi->first < best_cost)
{
best_cost = pi->first;
best_cost_time = pi->second;
}
if (pi->first == best_cost && pi->second < best_cost_time)
{
best_cost_time = pi->second;
}
}
}
cout << best_cost << " " << best_cost_time << endl;
}
return 0;
}
/*
4 7
0 5 2 3
5 0 2 3
3 1 0 2
3 3 2 0
0 2 2 7
2 0 1 2
2 2 0 5
7 2 5 0
0 0
*/
Turn on the LOG you will be able to see the Floyd Warshall table for each iteration, each cell has set of a (cost, time) pair. They are supposed to be the cost/time pairs of all non-dominated paths.
I would really appreciate if someone can tell me what's wrong. Thanks a lot in advance!
Try this test:
4 10
0 1 1 1000
1 0 1 1
1 1 0 1
1000 1 1 0
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
Basically you need to ensure distances[i][j] <= time_budget before
shortest_paths[i][j][0].push_back(pair<int, int>(tolls[i][j], distances[i][j]));