How to replace a common array int playersStartPos[100] with a std::map in BFS algorithm? This algorithm finds the shortest path between all two vertices. It works, but in some cases it takes more than 1 second to proceed all vertices. So I have to replace this loop for (int j = 0; j < K; j++) { //BAAAADDDDDDwith a std::map and do the search by key. But it appears it works even worse (should be better I know it 100%). How to modify an algorithm to use std::map?.
Thank you.
**INPUT**
7 3
1 1
2 0 2
2 1 4
1 4
3 2 3 5
2 4 6
1 5
0 3 6
**OUTPUT**
0 4 5
4 0 3
5 3 0
1 2
#include <iostream>
#include <stdio.h>
#include <vector>
#include <queue>
#include <map>
using namespace std;
vector<vector<int>> adjList;
int N = 0; //vertices quantity
int K = 0; //players quantity
int playersStartPos[100];
int res[100][100];
void read()
{
FILE* fp = fopen("input2.txt", "r");
fscanf(fp, "%d", &N);
fscanf(fp, "%d", &K);
for (int i = 0; i < N; i++) {
int size = 0;
fscanf(fp, "%d", &size);
vector<int> adjacency(size);
for (int j = 0; j < size; j++) {
int to = 0;
fscanf(fp, "%d", &to);
adjacency[j] = to;
}
adjList.push_back(adjacency);
}
for (int player = 0; player < K; player++) {
int pos = 0;
fscanf(fp, "%d", &pos);
//cout << pos << " ";
playersStartPos[player] = pos;
}
//fclose(fp);
}
int bfs(int start, int ind)
{
queue<int> q;
vector<bool> used(N, 0);
vector<int> path(N);
q.push(start);
used[start] = true;
path[start] = -1;
while (!q.empty()) {
int currentVertex = q.front();
q.pop();
for (size_t i = 0; i < adjList[currentVertex].size(); ++i) {
int to = adjList[currentVertex][i];
if (!used[to]) {
path[to] = path[currentVertex] + 1;
used[to] = true;
q.push(to);
for (int j = 0; j < K; j++) { //BAAAADDDDDD
if (to == playersStartPos[j]) {
res[ind][j] = path[to] + 1;
}
}
}
}
}
return 0;
}
void find()
{
for (int i = 0; i < K; i++) {
bfs(playersStartPos[i], i);
}
}
void write()
{
int min = N;
int one = 0;
int two = 0;
for (int i = 0; i < K; i++) {
for (int j = 0; j < K; j++) {
if (res[i][j] == 0) {
continue;
}
if (min > res[i][j]) {
min = res[i][j];
one = i;
two = j;
}
}
}
FILE* fp = fopen("output.txt", "w");
for (int i = 0; i < K; i++) {
for (int j = 0; j < K; j++) {
fprintf(fp, "%d ", res[i][j]);
}
fprintf(fp, "%c", '\n');
}
fprintf(fp, "%d %d\n", one, two);
//fclose(fp);
}
int main()
{
read();
find();
write();
return 0;
}
UPDATE WITH A MAP
#include <iostream>
#include <stdio.h>
#include <vector>
#include <queue>
#include <map>
using namespace std;
vector<vector<int>> adjList;
int N = 0; //vertices quantity
int K = 0; //players quantity
map<int, int> playersStartPos;
//int playersStartPos[100];
int res[100][100];
void read()
{
FILE* fp = fopen("input2.txt", "r");
fscanf(fp, "%d", &N);
fscanf(fp, "%d", &K);
for (int i = 0; i < N; i++) {
int size = 0;
fscanf(fp, "%d", &size);
vector<int> adjacency(size);
for (int j = 0; j < size; j++) {
int to = 0;
fscanf(fp, "%d", &to);
adjacency[j] = to;
}
adjList.push_back(adjacency);
}
for (int player = 0; player < K; player++) {
int pos = 0;
fscanf(fp, "%d", &pos);
//cout << pos << " ";
playersStartPos[player] = pos;
}
/*for (int i = 0; i < adjList.size(); i++) {
cout << "From: " << i << " to: ";
for (int j = 0; j < adjList[i].size(); j++) {
cout << " " << adjList[i][j];
}
cout << endl;
}*/
//fclose(fp);
}
int bfs(int start, int ind)
{
queue<int> q;
vector<int> used(N, 0);
vector<int> path(N);
q.push(start);
used[start] = true;
path[start] = -1;
while (!q.empty()) {
int currentVertex = q.front();
q.pop();
for (size_t i = 0; i < adjList[currentVertex].size(); ++i) {
int to = adjList[currentVertex][i];
if (!used[to]) {
path[to] = path[currentVertex] + 1;
used[to] = 1;
q.push(to);
for (int j = 0; j < K; j++) {
auto it = playersStartPos.find(j);
if (it == playersStartPos.end()) continue;
if (to == it->second) {
//if (to == playersStartPos[j]) {
//cout << path[to] + 1 << endl;
res[ind][it->first] = path[to] + 1;
//res[ind][j] = path[to] + 1;
//break;
}
}
}
}
}
return 0;
}
void find()
{
for (int i = 0; i < K; i++) {
bfs(playersStartPos[i], i);
}
}
void write()
{
int min = N;
int one = 0;
int two = 0;
for (int i = 0; i < K; i++) {
for (int j = 0; j < K; j++) {
if (res[i][j] == 0) {
continue;
}
if (min > res[i][j]) {
min = res[i][j];
one = i;
two = j;
}
}
}
FILE* fp = fopen("output.txt", "w");
for (int i = 0; i < K; i++) {
for (int j = 0; j < K; j++) {
fprintf(fp, "%d ", res[i][j]);
}
fprintf(fp, "%c", '\n');
}
fprintf(fp, "%d %d\n", one, two);
//fclose(fp);
}
int main()
{
read();
find();
write();
return 0;
}
Here it is solution
#include <iostream>
#include <stdio.h>
#include <vector>
#include <queue>
#include <map>
using namespace std;
vector<vector<int>> adjList;
int N = 0; //vertices quantity
int K = 0; //players quantity
map<int, int> playersStartPos;
int res[100][100];
void read()
{
FILE* fp = fopen("input.txt", "r");
fscanf(fp, "%d", &N);
fscanf(fp, "%d", &K);
for (int i = 0; i < N; i++) {
int size = 0;
fscanf(fp, "%d", &size);
vector<int> adjacency(size);
for (int j = 0; j < size; j++) {
int to = 0;
fscanf(fp, "%d", &to);
adjacency[j] = to;
}
adjList.push_back(adjacency);
}
for (int player = 0; player < K; player++) {
int vertex = 0;
fscanf(fp, "%d", &vertex);
playersStartPos[vertex] = player;
}
fclose(fp);
}
int bfs(int start, int ind)
{
queue<int> q;
vector<int> used(N, 0);
vector<int> path(N);
q.push(start);
used[start] = true;
path[start] = -1;
while (!q.empty()) {
int currentVertex = q.front();
q.pop();
for (size_t i = 0; i < adjList[currentVertex].size(); ++i) {
int to = adjList[currentVertex][i];
if (!used[to]) {
path[to] = path[currentVertex] + 1;
used[to] = 1;
q.push(to);
auto it = playersStartPos.find(to);
if (it == playersStartPos.end()) continue;
if (to == it->first) {
res[ind][it->second] = path[to] + 1;
}
}
}
}
return 0;
}
void find()
{
map<int, int>::iterator it;
for (it = playersStartPos.begin(); it != playersStartPos.end(); it++) {
bfs(it->first, it->second);
}
}
void write()
{
int min = N;
int one = 0;
int two = 0;
for (int i = 0; i < K; i++) {
for (int j = 0; j < K; j++) {
if (res[i][j] == 0) {
continue;
}
if (min > res[i][j]) {
min = res[i][j];
one = i;
two = j;
}
}
}
FILE* fp = fopen("output.txt", "w");
for (int i = 0; i < K; i++) {
for (int j = 0; j < K; j++) {
fprintf(fp, "%d ", res[i][j]);
}
fprintf(fp, "%c", '\n');
}
fprintf(fp, "%d %d\n", one, two);
fclose(fp);
}
int main()
{
read();
find();
write();
return 0;
}
Related
I'm getting an error message in Codeblocks C++ 'Program received signal SIGSEGV, Segmentation fault' in comparison between a vector element and a size of vector of vectors inside for loop (line 133 if (parz_przestrzenie[i] != parz_dystanse[i].size())).
Could anyone tell me why?
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int bloki_parz[100000], bloki_nieparz[100000];
int silnia(int n)
{
int liczba = 1;
for (int i = 1; i <= n; i++)
{
liczba *= i;
}
return liczba;
}
int main()
{
int n, czapka, wolne_miejsca = 0, wynik = 1;
vector<int> parz, nieparz, parz_przestrzenie, nieparz_przestrzenie, parz_przestrzenie2, nieparz_przestrzenie2;
vector<vector<int>> parz_dystanse;
vector<vector<int>> nieparz_dystanse;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> czapka;
if (i % 2 == 0)
{
parz.push_back(czapka);
}
else
{
nieparz.push_back(czapka);
}
}
int parz_size = parz.size(), nieparz_size = nieparz.size();
// sprawdzamy czy dane nie sÂą sprzeczne ; gdy zabraknie nam miejsc do rozmieszczania
vector<int> parz_duplicate = parz;
vector<int> nieparz_duplicate = nieparz;
parz_duplicate.erase(unique(parz_duplicate.begin(), parz_duplicate.end()), parz_duplicate.end());
nieparz_duplicate.erase(unique(nieparz_duplicate.begin(), nieparz_duplicate.end()), nieparz_duplicate.end());
int parz_dupl_size = parz_duplicate.size(), nieparz_dupl_size = nieparz_duplicate.size();
if (parz_size < nieparz_dupl_size)
{
cout << 0 << endl;
return 0;
}
if (nieparz_size < parz_dupl_size)
{
cout << 0 << endl;
return 0;
}
for (int i = 0; i < parz_size - 1; i++)
{
if (parz[i] == parz[i + 1])
{
bloki_parz[i + 1] = 1;
}
}
for (int i = 0; i < nieparz_size - 1; i++)
{
if (nieparz[i] == nieparz[i + 1])
{
bloki_nieparz[i] = 1;
}
}
for (int i = 0; i < parz_size; i++)
{
vector<int> bloczek;
for (int j = i; j < parz_size; j++)
{
if (parz[j] != parz[j + 1])
{
bloczek.push_back(parz[j]);
}
else
{
i += 1;
break;
}
}
if (bloczek.size() != 0)
{
parz_dystanse.push_back(bloczek);
}
}
int parz_dyst_size = parz_dystanse.size();
if (parz[parz_size - 1] != parz[parz_size - 2])
{
parz_dystanse[parz_dyst_size - 1].push_back(parz[parz_size - 1]);
}
for (int i = 0; i < nieparz_size; i++)
{
vector<int> bloczek;
for (int j = i; j < nieparz_size; j++)
{
if (nieparz[j] != nieparz[j + 1])
{
bloczek.push_back(nieparz[j]);
}
else
{
i += 1;
break;
}
}
if (bloczek.size() != 0)
{
nieparz_dystanse.push_back(bloczek);
}
}
int nieparz_dyst_size = nieparz_dystanse.size();
int current_wynik = 0;
for (int i = 0; i < nieparz_size; i++)
{
if (bloki_parz[i] == 0)
{
current_wynik++;
}
else
{
if (current_wynik != 0)
{
parz_przestrzenie.push_back(current_wynik);
}
current_wynik = 0;
}
}
parz_przestrzenie.push_back(current_wynik);
current_wynik = 0;
for (int i = 0; i < parz_size; i++)
{
if (bloki_nieparz[i] == 0)
{
current_wynik++;
}
else
{
if (current_wynik != 0)
{
nieparz_przestrzenie.push_back(current_wynik);
}
current_wynik = 0;
}
}
nieparz_przestrzenie.push_back(current_wynik);
int parz_przest_size = parz_przestrzenie.size(), nieparz_przest_size = nieparz_przestrzenie.size();
for (int i = 0; i < 1; i++)
{
if (parz_przestrzenie[i] != parz_dystanse[i].size())
{
wynik *= parz_przestrzenie[i];
wolne_miejsca++;
}
}
for (int i = 0; i < nieparz_przest_size; i++)
{
if (nieparz_przestrzenie[i] != nieparz_dystanse[i].size())
{
wynik *= nieparz_przestrzenie[i];
wolne_miejsca++;
}
}
cout << wynik * silnia(wolne_miejsca) << endl;
}
parz_dystanse is a vector of a vector. In this case the return value of parz_dystanse.size() is a long unsigned int, whereas an element of parz_przestrzenie is an int.
You need to make explicit that parz_dystanse.size() returns an int in order to make comparitions between integer expressions of different signedness.
This will fix that problem:
if (parz_przestrzenie[i] != (int)parz_dystanse[i].size())
I am trying to solve shortest path for big graph using dijkstra algorithm.
Problem is when I am executing program in CLion I am getting std::bad alloc, always at node 491, however when I tried do the same on my Ubuntu VM, I am getting core dumped on the beggining.
I am new to c++ so it is hard for me to understand why does it happen.
Here is my code:
Utils:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <ctime>
#define INFINITY 9999999
int maxNode = 0;
using namespace std;
vector<int> loadFile(const string &path) {
vector<int> graph;
ifstream file;
file.open(path);
if (!file.fail()) {
string line;
while (getline(file, line)) {
stringstream ss(line);
for (int i; ss >> i;) {
if (i + 1 > maxNode)
maxNode = i + 1;
graph.push_back(i);
if (ss.peek() == ';')
ss.ignore();
}
}
file.close();
}
return graph;
}
int **formatGraph(vector<int> inData) {
int **graph = 0;
int currentIndex = 0;
int srcNode = inData[0];
int dstNode = inData[1];
int cost = inData[2];
graph = new int *[maxNode];
for (int i = 0; i < maxNode; i++) {
graph[i] = new int[maxNode];
for (int j = 0; j < maxNode; j++) {
if (srcNode == i && dstNode == j) {
graph[i][j] = cost;
currentIndex++;
srcNode = inData[currentIndex * 3];
dstNode = inData[currentIndex * 3 + 1];
cost = inData[currentIndex * 3 + 2];
//printf("%d %d\n", i, j);
} else
graph[i][j] = 0;
}
}
for (int i = 0; i < maxNode; i++) {
for (int j = 0; j < maxNode; j++) {
graph[j][i] = graph[i][j];
}
}
return graph;
}
Algorithm:
void dijkstra(int **G, int n, int startnode) {
printf("%d\n", startnode);
int **cost = new int *[maxNode];
int distance[maxNode], pred[maxNode];
int visited[maxNode], count, mindistance, nextnode, i, j;
for (i = 0; i < n; i++) {
cost[i] = new int[maxNode];
for (j = 0; j < n; j++)
cost[i][j] = 0;
}
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (G[i][j] == 0)
cost[i][j] = INFINITY;
else
cost[i][j] = G[i][j];
for (i = 0; i < n; i++) {
distance[i] = cost[startnode][i];
pred[i] = startnode;
visited[i] = 0;
}
distance[startnode] = 0;
visited[startnode] = 1;
count = 1;
while (count < n - 1) {
mindistance = INFINITY;
for (i = 0; i < n; i++) {
if (distance[i] < mindistance && !visited[i]) {
mindistance = distance[i];
nextnode = i;
}
}
visited[nextnode] = 1;
for (i = 0; i < n; i++) {
if (!visited[i]) {
if (mindistance + cost[nextnode][i] < distance[i]) {
distance[i] = mindistance + cost[nextnode][i];
pred[i] = nextnode;
}
}
}
count++;
}
delete[] cost;
for (i = 0; i < n; i++)
if (i != startnode) {
j = i;
do {
j = pred[j];
} while (j != startnode);
}
}
And here is my main function:
int main() {
vector<int> graph = loadFile("..\\data\\newFile2.csv");
int **graphConverted = formatGraph(graph);
//printMatrix(graphConverted);
clock_t begin = clock();
for (int i = 0; i < maxNode; i++)
dijkstra(graphConverted, maxNode, i);
clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
printf("\nTime: %f", elapsed_secs);
return 0;
}
First the data is loaded into vector, and then it is converted to adjacency matrix.
Data is stored in form:
src_node;dst_node;cost
1;2;3
1;3;30
1;66;20
etc.
Dataset consinsts of 1004 nodes and 25571 edges.
Could you please suggest me any solution how to fix this?
In dijkstra you have dynamic memory allocations here:
int **cost = new int *[maxNode];
and here in a loop over i:
cost[i] = new int[maxNode];
You have only one call to delete[] in this function:
delete[] cost;
So all the allocations from the second new line are guaranteed to be leaked. After a while you will be out-of-memory, resulting in the std::bad_alloc.
You need to match each new[] call with exactly one delete[] call.
Don't use new/delete at all. Instead declare all your arrays as std::vector, which will take care of this automatically.
Also don't use variable-length arrays such as
int distance[maxNode], pred[maxNode];
They are a non-standard compiler extension. Make these std::vector as well.
I am trying to implement a parallel code for graph isomorphism(checking if 2 graphs are isomorphic or not) using openmp. I have the sequential code below, written in C++ which works only for regular graphs.
I have taken the input from a text file (input.txt) which contains number of nodes and 2 adjacency matrices representing 2 graphs. The output.txt file indicates whether the graphs are isomorphic or NON isomorphic along with the execution time.
I have used is_regular() function to check if a graph is regular graph or not.
Can someone please help me parallelize this code using openmp.
#include <time.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <string>
using namespace std;
bool is_regular(vector<string> &adj) {
int nv = adj.size();
int cnt = 0;
for (int j = 0; j < nv; ++j)
if (adj[0][j] == '1') ++cnt;
for (int i = 1; i < nv; ++i) {
int sch = 0;
for (int j = 0; j < nv; ++j)
if (adj[i][j] == '1') ++sch;
if (sch != cnt) return false;
}
return true;
}
vector<vector<int> > foo1(vector<string> &adj, char R) {
int nv = adj.size();
vector<vector<int> > res;
for (int v1 = 0; v1 < nv; ++v1) {
vector<int> tmp;
vector<bool> b(nv);
vector<int> p, q;
p.push_back(v1);
b[v1] = true;
while (!p.empty()) {
q.clear();
for (size_t i = 0; i < p.size(); ++i) {
for (int j = 0; j < nv; ++j)
{
if (!b[j] && adj[p[i]][j] == R) {
b[j] = true;
q.push_back(j);
}
}
}
if (q.empty()) break;
vector<int> d(p.size());
vector<int> e(q.size());
for (size_t i = 0; i < p.size(); ++i) {
for (size_t j = 0; j < q.size(); ++j) {
if (adj[p[i]][q[j]] == R) {++d[i]; --e[j];}
}
}
sort(d.begin(), d.end());
sort(e.begin(), e.end());
copy(d.begin(), d.end(), back_inserter(tmp));
copy(e.begin(), e.end(), back_inserter(tmp));
p.swap(q);
}
res.push_back(tmp);
}
sort(res.begin(), res.end());
return res;
}
vector<vector<int> > foo2(vector<string> &adj, char R) {
int nv = adj.size();
vector<vector<int> > res;
for (int v1 = 0; v1 < nv; ++v1) {
for (int v2 = v1 + 1; v2 < nv; ++v2) {
vector<int> tmp;
vector<bool> b(nv);
vector<int> p, q;
p.push_back(v1);
p.push_back(v2);
b[v1] = true;
b[v2] = true;
while (!p.empty()) {
q.clear();
for (size_t i = 0; i < p.size(); ++i) {
for (int j = 0; j < nv; ++j) {
if (!b[j] && adj[p[i]][j] == R) {
b[j] = true;
q.push_back(j);
}
}
}
if (q.empty()) break;
vector<int> d(p.size());
vector<int> e(q.size());
for (size_t i = 0; i < p.size(); ++i) {
for (size_t j = 0; j < q.size(); ++j) {
if (adj[p[i]][q[j]] == R) {++d[i]; --e[j];}
}
}
sort(d.begin(), d.end());
sort(e.begin(), e.end());
copy(d.begin(), d.end(), back_inserter(tmp));
copy(e.begin(), e.end(), back_inserter(tmp));
p.swap(q);
}
res.push_back(tmp);
}
}
sort(res.begin(), res.end());
return res;
}
vector<vector<int> > foo3(vector<string> &adj, char R) {
int nv = adj.size();
vector<vector<int> > res;
for (int v1 = 0; v1 < nv; ++v1) {
for (int v2 = v1 + 1; v2 < nv; ++v2) {
for (int v3 = v2 + 1; v3 < nv; ++v3) {
vector<int> tmp;
vector<bool> b(nv);
vector<int> p, q;
p.push_back(v1);
p.push_back(v2);
p.push_back(v3);
b[v1] = true;
b[v2] = true;
b[v3] = true;
while (!p.empty()) {
q.clear();
for (size_t i = 0; i < p.size(); ++i) {
for (int j = 0; j < nv; ++j) {
if (!b[j] && adj[p[i]][j] == R) {
b[j] = true;
q.push_back(j);
}
}
}
if (q.empty()) break;
vector<int> d(p.size());
vector<int> e(q.size());
for (size_t i = 0; i < p.size(); ++i) {
for (size_t j = 0; j < q.size(); ++j) {
if (adj[p[i]][q[j]] == R) {++d[i]; --e[j];}
}
}
sort(d.begin(), d.end());
sort(e.begin(), e.end());
copy(d.begin(), d.end(), back_inserter(tmp));
copy(e.begin(), e.end(), back_inserter(tmp));
p.swap(q);
}
res.push_back(tmp);
}
}
}
sort(res.begin(), res.end());
return res;
}
int main() {
int nt = 1;
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int n;
int tc = 0;
while (cin >> n) {
vector<string> adj1(n);
vector<string> adj2(n);
for (int i = 0; i < n; ++i) cin >> adj1[i];
for (int i = 0; i < n; ++i) cin >> adj2[i];
clock_t start = clock();
string answer = "NON-isomorphic";
if (!is_regular(adj1) || !is_regular(adj2)) {
answer = "Non regular graph";
goto mmm;
}
if (foo1(adj1,'1') != foo1(adj2,'1') || foo1(adj1,'0') != foo1(adj2,'0')) {
answer += " * ";
goto mmm;
}
if (foo2(adj1,'1') != foo2(adj2,'1') || foo2(adj1,'0') != foo2(adj2,'0')) {
answer += " ** ";
goto mmm;
}
if (foo3(adj1,'1') != foo3(adj2,'1') || foo3(adj1,'0') != foo3(adj2,'0')) {
answer += " ***";
goto mmm;
}
answer = "isomorphic";
mmm:
++tc;
printf("%d) n = %d %s", tc, n, answer.c_str());
printf(" %f\n", (double)(clock() - start) / CLOCKS_PER_SEC);
}
return 0;
}
I am working on a code for gaussian reduction, but for some reason I am getting the error:
Exception thrown at 0x00A9F6DF in Excersise-7-3.exe: 0xC0000005: Access violation writing location 0xFDFDFDFD.
at S[h][0] = i; (line 147)
I cant seem to resolve this. What should I do? How can I prevent this from happening in the future?
#include "stdafx.h"
#include "Gauss.h"
#include <fstream>
Gauss::Gauss()
{
x.resize(v.size());
vector<double>::iterator it;
for (it = x.begin(); it != x.end(); it++)
{
v[*it] = 0;
}
S = new double*[m];
for (int i = 0; i < m; i++)
{
S[i] = new double[3];
for (int j = 0; j < 3; j++)
{
S[i][j] = 0;
}
}
}
Gauss::~Gauss()
{
}
bool Gauss::read_vector(string filename)
{
ifstream in;
in.open(filename);
if (in.fail())
{
cout << "File could not be opened." << endl;
return false;
}
in >> size;
for (int i = 0; i < size; i++)
{
int y;
in >> y;
v.push_back(y);
}
in.close();
return true;
}
bool Gauss::read_matrix(string filename)
{
ifstream in;
in.open(filename);
if (in.fail())
{
cout << "File could not be opened." << endl;
return false;
}
in >> m;
in >> n;
A = new double *[m];
for (int i = 0; i < m; i++)
{
A[i] = new double[n];
for (int k = 0; k < n; k++)
{
in >> A[i][k];
}
}
in.close();
return true;
}
void Gauss::print_vector()
{
for (int i = 0; i < size; i++)
cout << v[i] << endl;
}
void Gauss::print_matrix()
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
cout << A[i][j] << " ";
}
cout << endl;
}
}
void Gauss::elimination(int &i, int &k)
for (int j = 0; j < m - 1; j++)
{
if(j != i)
{
double fraction = A[j][k] / A[i][k];
for (int l = 0; l < n; l++)
{
A[j][l] = A[j][l] - fraction*A[i][l];
v[j] = v[j] - fraction*v[i];
}
}
}
}
void Gauss::row_swap(int &i, int &k)
{
double sub;
for (int j = 0; j < n; j++)
{
sub = A[i][j];
A[i][j] = A[k][j];
A[k][j] = sub;
}
{
sub = v[i];
v[i] = v[k];
v[k] = sub;
}
}
void Gauss::reduction()
{
int h = 0;
int i = 0;
int k = 0;
while (i != m || k != n)
{
if (A[i][k] != 0)
{
elimination(i, k);
S[h][0] = i;
S[h][1] = k;
S[h][2] = A[i][k];
h++;
cout << h;
}
else
{
for (int j = i + 1; j < m; j++)
{
if (A[j][k] > 0)
{
row_swap(i, k);
elimination(i, k);
S[h][0] = i;
S[h][1] = k;
S[h][2] = A[i][k];
h++;
}
else
{
k++;
}
}
}
i++;
k++;
}
}
void Gauss::solution()
{
for (int j = 0; j < m; j++)
{
x[S[j][1]] = v[S[j][0]] / S[j][2];
}
}
I am trying to solve http://www.spoj.com/problems/BOTTOM/
Here are the steps I am following:
1) Find the strongly connected components using Kosaraju's algorithm. 2) Consider a strongly connected component. Consider an edge u. Now consider all edges from u to some vertice v. If v lies in some other SCC, eliminate the whole strongly conected component. Else include all the elements in the solution.
However, I am constantly getting WA. Please help.
Here is my code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <fstream>
#include <iterator>
#include <queue>
using namespace std;
int k = 0;
int V, E;
bool fix[5001];
bool fix2[5001];
int compNum[5001];
void dfs(int v, vector< vector<int> >&G, bool *fix, vector <int> &out) {
fix[v] = true;
for (int i = 0; i < G[v].size(); i++) {
int u = G[v][i];
if (!fix[u]) {
fix[u] = true;
dfs(u, G, fix, out);
}
}
out.push_back(v);
}
void dfs2(int v, vector< vector<int> >&G, bool *fix2, vector < vector<int> > &components) {
fix2[v] = true;
for (int i = 0; i < G[v].size(); i++) {
int u = G[v][i];
if (!fix2[u]) {
fix2[u] = true;
dfs2(u, G, fix2, components);
}
}
components[k].push_back(v);
compNum[v] = k;
}
int main() {
int a, b;
while (true) {
cin >> V; if (V == 0) break; cin >> E;
vector< vector<int> >G(V + 1);
vector< vector<int> >G2(V + 1);
vector<int>out;
vector < vector<int> >components(V + 1);
for (int i = 0; i < E; i++) {
cin >> a >> b;
G[a].push_back(b);
G2[b].push_back(a);
}
for (int i = 1; i <= V; i++) {
if (!fix[i])
dfs(i, G, fix, out);
}
reverse(out.begin(), out.end());
for (int i = 0; i < out.size(); i++){
if (!fix2[out[i]]) {
dfs2(out[i], G2, fix2, components);
k++;
}
}
vector<int>gamotana;
for (int i = 0; i < components.size(); i++) {
for (int j = 0; j < components[i].size(); j++) {
bool check = true;
for (int z = 0; z < G[components[i][j]].size(); z++)
{
if (compNum[G[components[i][j]][z]] != i)
{
check = false; goto next123;
}
}
if (check)
gamotana.push_back(components[i][j]);
}
next123:;
}
sort(gamotana.begin(), gamotana.end());
for (int i = 0; i < gamotana.size(); i++)
cout << gamotana[i] << " ";
for (int i = 0; i < 5001; i++) {
fix[i] = false;
fix2[i] = false;
compNum[i] = -1;
}
k = 0;
cout << endl;
}
return 0;
}
In your algorithm description you say you eliminate the entire connected component if some edge leads to a different component.
However, in your code you appear to add all vertices j in component i to your solution until you find an edge leading out. In other words, even if a component is not a sink you may still incorrectly report some of the vertices as being sinks.
I imagine you should do something more like this:
for (int i = 0; i < components.size(); i++) {
for (int j = 0; j < components[i].size(); j++) {
for (int z = 0; z < G[components[i][j]].size(); z++)
{
if (compNum[G[components[i][j]][z]] != i)
{
goto next123;
}
}
}
for (int j = 0; j < components[i].size(); j++)
gamotana.push_back(components[i][j]);
next123:;
}
Of course, there may be more issues. I would recommend you try constructing and testing some small examples first, and perhaps testing against a brute force solver to identify failing cases.
#include<bits/stdc++.h>
using namespace std;
void dfs(vector<int>* edges, stack<int>& finishedVertices, bool* visited, int n, int start){
visited[start] = true;
for(int i = 0 ; i < edges[start].size() ; i++){
int node = edges[start][i];
if(!visited[node]){
dfs(edges, finishedVertices, visited, n, node);
}
}
finishedVertices.push(start);
}
void dfs_reverse(vector<int>* edgesT, bool* visited, unordered_map<int,vector<int>>& SCC, int node, int k){
SCC[k].push_back(node);
visited[node] = true;
for(int i = 0 ; i < edgesT[node].size() ; i++){
int new_node = edgesT[node][i];
if(!visited[new_node]){
dfs_reverse(edgesT, visited, SCC, new_node, k);
}
}
}
void getSCC(vector<int>* edges, vector<int>* edgesT, int n){
bool* visited = new bool[n];
for(int i = 0 ; i < n ; i++){
visited[i] = false;
}
stack<int> finishedVertices;
for(int i = 0 ; i < n ; i++){
if(!visited[i]){
dfs(edges, finishedVertices, visited, n, i);
}
}
unordered_map<int,vector<int>> SCC;
int k = 0;
for(int i = 0 ; i < n ; i++){
visited[i] = false;
}
while(!finishedVertices.empty()){
int node = finishedVertices.top();
finishedVertices.pop();
if(!visited[node]){
dfs_reverse(edgesT, visited, SCC, node, k);
k++;
}
}
int flag = 1;
vector<int> ans;
vector<int> bottom;
for(int i = 0 ; i < k ; i++){
for(int j = 0 ; j < SCC[i].size(); j++){
ans.push_back(SCC[i][j]);
}
for(int m = 0 ; m < ans.size() ; m++){
int node = ans[m];
for(int j = 0 ; j < edges[node].size() ; j++){
int new_node = edges[node][j];
vector<int> :: iterator it;
it = find(ans.begin(), ans.end(), new_node);
if(it == ans.end()){
flag = 0;
break;
}
}
if(flag == 0)
break;
}
if(flag == 1){
for(int j = 0 ; j < ans.size() ; j++)
bottom.push_back(ans[j]);
}
flag = 1;
ans.clear();
}
sort(bottom.begin(), bottom.end());
for(int i = 0 ; i < bottom.size() ; i++)
cout << bottom[i] + 1 << " ";
cout << endl;
}
int main(){
while(true){
int n;
cin >> n;
if(n == 0)
break;
vector<int>* edges = new vector<int>[n];
vector<int>* edgesT = new vector<int>[n];
int e;
cin >> e;
for(int i = 0 ; i < e ; i++){
int x, y;
cin >> x >> y;
edges[x-1].push_back(y-1);
edgesT[y-1].push_back(x-1);
}
getSCC(edges, edgesT, n);
delete [] edges;
delete [] edgesT;
}
return 0;
}