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;
}
Related
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.
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?
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).
I use the following code to find maximal matching in bipartite graph
(I've tried to add a few comments):
#include <iostream>
using namespace std;
// definition of lists elements
//-------------------------------
struct slistEl
{
slistEl * next;
int data;
};
// definition objective type queue
//---------------------------------
class queue
{
private:
slistEl * head;
slistEl * tail;
public:
queue();
~queue();
bool empty(void);
int front(void);
void push(int v);
void pop(void);
};
queue::queue()
{
head = tail = NULL;
}
queue::~queue()
{
while(head) pop();
}
bool queue::empty(void)
{
return !head;
}
int queue::front(void)
{
if(head) return head->data;
else return -10000;
}
void queue::push(int v)
{
slistEl * p = new slistEl;
p->next = NULL;
p->data = v;
if(tail) tail->next = p;
else head = p;
tail = p;
}
void queue::pop(void)
{
if(head)
{
slistEl * p = head;
head = head->next;
if(!head) tail = NULL;
delete p;
}
}
//---------------
// main part
//---------------
queue Q; // queue
int *Color; // colors of vertexes
slistEl **graf; // adjacency array
int **C; // matrix of capacity
int **F; // matrix of nett flow
int *P; // array of prev
int *CFP; // array of residual capacity
int n,m,fmax,cp,v,u,i,j; //
bool esc; //
slistEl *pr, *rr; // pointer for list elements
int main(int argc, char *argv[])
{
// n - number of vertexes
// m - number of edges
cin >> n >> m;
Color = new int [n];
graf = new slistEl * [n];
for(i = 0; i < n; i++)
{
graf[i] = NULL;
Color[i] = 0;
}
C = new int * [n+2];
F = new int * [n+2];
for(i = 0; i <= n + 1; i++)
{
C[i] = new int [n+2];
F[i] = new int [n+2];
for(j = 0; j <= n + 1; j++)
{
C[i][j] = 0;
F[i][j] = 0;
}
}
P = new int [n+2];
CFP = new int [n+2];
// reading edges definition and adding to adjacency list
for(i = 0; i < m; i++)
{
cin >> v >> u;
pr = new slistEl;
pr->data = u;
pr->next = graf[v];
graf[v] = pr;
pr = new slistEl;
pr->data = v;
pr->next = graf[u];
graf[u] = pr;
}
for(i = 0; i < n; i++){
cin>> Color[i];
}
for(i = 0; i < n; i++)
if(Color[i] == -1)
{
for(pr = graf[i]; pr; pr = pr -> next) // neighbours of blue
C[i][pr->data] = 1; // capacity to red
C[n][i] = 1; // capacity to source
}
else C[i][n+1] = 1; // capacity edges to outfall
//** Edmonds-Karp algorithm **
fmax = 0;
while(true)
{
for(i = 0; i <= n + 1; i++) P[i] = -1;
P[n] = -2;
CFP[n] = MAXINT;
while(!Q.empty()) Q.pop();
Q.push(n);
esc = false;
while(!Q.empty())
{
v = Q.front(); Q.pop();
for(u = 0; u <= n + 1; u++)
{
cp = C[v][u] - F[v][u];
if(cp && (P[u] == -1))
{
P[u] = v;
if(CFP[v] > cp) CFP[u] = cp; else CFP[u] = CFP[v];
if(u == n+1)
{
fmax += CFP[n+1];
i = u;
while(i != n)
{
v = P[i];
F[v][i] += CFP[n+1];
F[i][v] -= CFP[n+1];
i = v;
}
esc = true; break;
}
Q.push(u);
}
}
if(esc) break;
}
if(!esc) break;
}
// showing reuslts
if(fmax > 0)
for(v = 0; v < n; v++)
for(u = 0; u < n; u++)
if((C[v][u] == 1) && (F[v][u] == 1))
cout << v << " - " << u << endl;
cout << endl;
// cleaning
delete [] Color;
for(i = 0; i < n; i++)
{
pr = graf[i];
while(pr)
{
rr = pr;
pr = pr->next;
delete rr;
}
}
delete [] graf;
for(i = 0; i <= n + 1; i++)
{
delete [] C[i];
delete [] F[i];
}
delete [] C;
delete [] F;
delete [] P;
delete [] CFP;
return 0;
}
It returns only one maximal matching. For example for data:
6 7
0 3 0 5
1 3 1 4 1 5
2 3 2 5
1 1 1 -1 -1 -1
But there are more maximal matchings.
I don't know, how should I modify it to get all results and I would like to ask somebody for help. Thank you in advance.
That algorithm is only efficient to get you a maximum matching.
If you want all maximal matching you have to consider the case where any matching is a maximal matching. In that case you have N! possibilities.
Since you will need to visit all solutions your complexity will be O(N!) at least. Therefore, forget the code you have, you can just try all possible matchings using a recursive algorithm and keep the set of maximal matching you get.
I have this code to find bridges in a connected graph:
void dfs (int v, int p = -1) {
used[v] = true;
tin[v] = fup[v] = timer++;
for (size_t i=0; i<g[v].size(); ++i) {
int to = g[v][i];
if (to == p) continue;
if (used[to])
fup[v] = min (fup[v], tin[to]);
else {
dfs (to, v);
fup[v] = min (fup[v], fup[to]);
if (fup[to] > tin[v])
printf("%d %d", v, to);
}
}
}
How to rewrite it without using recursion? I know, it's possible to do it and I should use stack, but this line must be executed after recursive call of dfs() and I can't achieve with a stack:
fup[v] = min(fup[v], fup[to])
So, how to rewrite my algorithm iteratively?
You want to make a "stack frame" structure
struct Frame {
Frame(int v, int p, int i, Label label);
int v;
int p;
int i;
};
// constructor here
and, as you say, a stack<Frame>. Between all of these fields, it's possible to simulate the call stack (untested code to give the general idea).
void dfs(int v, int p = -1) {
stack<Frame> st;
st.push(Frame(v, p, 0));
do {
Frame fr(st.top());
st.pop();
v = fr.v;
p = fr.p;
int i(fr.i);
if (i > 0) {
int to(g[v][i - 1]);
fup[v] = min(fup[v], fup[to]);
if (fup[to] > tin[v]) { printf("%d %d", v, to); }
if (i == g[v].size()) { continue; }
} else if (i == 0) {
used[v] = true;
tin[v] = fup[v] = timer++;
}
int to(g[v][i]);
if (to == p) { continue; }
if (used[to]) {
fup[v] = min(fup[v], tin[to]);
} else {
st.push(Frame(to, v, 0));
}
st.push(Frame(v, p, i + 1));
} while (!st.empty());
}
Sorry for the late reply.
Change code of previous answer and now it works fine.
Tested in contest task to find all bridges in connected Graph.
Hope it will help you.
// Copyright 2020 Kondratenko Evgeny
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
struct Frame {
Frame(int v, int p, int i) : v(v), p(p), i(i) {
}
int v;
int p;
int i;
};
void DFS(int n,
const std::vector<std::vector<int>> &G,
const std::vector<std::vector<int>> &weights) {
std::vector<bool> used(n + 1, false);
std::vector<int> ret(n + 1); // the same as tup
std::vector<int> enter(n + 1); // the same as tin
std::stack<Frame> s;
s.push(Frame(1, -1, 0));
int time = 1;
while (!s.empty()) {
Frame f = s.top();
s.pop();
int v = f.v;
int p = f.p;
int i = f.i;
if (i == 0) {
enter[v] = ret[v] = time++;
used[v] = true;
}
// First part works befor DFS call
if (i < G[v].size()) {
int to = G[v][i];
s.push(Frame(v, p, i + 1));
if (to != p) {
if (used[to]) {
ret[v] = std::min(ret[v], enter[to]);
} else {
s.push(Frame(to, v, 0));
}
}
}
/*
Generally here is virtual DFS recursive call, which we are simulate now
*/
// Second part after DFS call
if (i > 0 && i <= G[v].size()) {
int to = G[v][i - 1];
if (to != p) {
ret[v] = std::min(ret[v], ret[to]);
if (ret[to] > enter[v]) {
std::cout << "bridge between: " << v << " and " << to;
std::cout << ", with weight: " << weights[v][i - 1] << std::endl;
}
}
}
}
}
int main() {
int n, m; // n - number of vertex, m - number of edges
std::cin >> n >> m;
std::vector<std::vector<int>> G(n + 1, std::vector<int>()); // your Graph
std::vector<std::vector<int>> weights(n + 1, std::vector<int>());
for (int i = 0; i < m; ++i) { // read edges with weigths
int u, v, w;
std::cin >> u >> v >> w;
G[u].push_back(v);
G[v].push_back(u);
weights[u].push_back(w);
weights[v].push_back(w);
}
DFS(n, G, weights);
return 0;
}