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;
}
Related
This is the question I am trying to code. I have written the following code but I don't know how can I store the elements in the vector in getComponent() function and retrieve it inside main function.
I have used ans as a vector variable. I am passing its address so that I do not have to return anything. But I am getting compilation error while running the code.
#include<vector>
#include <bits/stdc++.h>
using namespace std;
void getComponent(int **edges, int n, int sv, int * visited, vector<int>*ans){
visited[sv] = 1;
ans->push_back(sv);
for(int i = 0; i < n; i++){
if(i == sv)continue;
if(edges[sv][i] == 1){
if(visited[i] == 0)
getComponent(edges, n, i, visited, ans);
}
}
}
int main() {
// Write your code here
int n, e;
cin>>n>>e;
int **edges = new int *[n];
for(int i = 0; i < n; i++){
edges[i] = new int[n];
for(int j = 0; j < n; j++){
edges[i][j] = 0;
}
}
for(int i = 0; i <e; i++){
int a, b;
cin>>a>>b;
edges[a][b] = 1;
edges[b][a] = 1;
}
int *visited = new int[n];
for(int i = 0; i < n; i++)
visited[i] = 0;
for(int i = 0; i < n; i++){
if(visited[i] == 0){
vector<int>*ans;
getComponent(edges, n, i, visited, ans);
for (auto x : ans)
cout << x << " ";
cout<<endl;
}
}
}
You need to actually create an ans vector and pass it's address:
for(int i = 0; i < n; i++){
if(visited[i] == 0){
vector<int> ans;
getComponent(edges, n, i, visited, &ans);
for (auto x : ans)
cout << x << " ";
cout<<endl;
}
}
After that you should replace all C-style arrays with std::vector and pass references instead of pointers.
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;
}
so I am trying to implement the following pseudocode but it will not work as it is supposed to. Here is the problem description in the slide, "Given an integer bound, "W", and a collection of "n" items, each with a positive integer weight "wi", find a subset S of items that: maximizes Sigma sub i where i is an element of S "wi" while keeping this sum less than or equal or to W. I will attach the following slides for where I am getting the problem description and pseudocode from. The problem with my implementation is that it will only find the total max value and not the value that is less than or equal to the weight. So for example, if I had Weight 10 (W = 10) and items 3 (n = 3) with item weights 1, 4, & 8 then the following answer should be 9; however, my solution gives 12. Here are the slides (*Please not, where it says w[j] it is meant to be w[i] - the slide had a typo):
Here is my code that implements the pseudocode:
#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int max(int a, int b, int c) {
if (a >= b)
return a;
else
return b;
}
int optimal_weight(int W, const vector<int> &wt, int n){
vector<vector<int> > M;
M.resize(n+1);
for(int i = 0; i < n+1; ++i){
M[i].resize(W+1);
}
for(int w = 0; w < W+1; w++){
M[0][w] = 0;
}
for(int i = 1; i < n+1; i++){
M[i][0] = 0;
}
for(int i = 1; i < n+1; i++){
for(int w = 0; w < W+1; w++){
if(wt[i] > w){
M[i][w] = M[i-1][w];
}
M[i][w] = max(M[i-1][w], wt[i] + M[i-1][W-wt[i]], W);
}
}
for (int i = 0; i <= n; i++)
{
for (int j = 0; j <= W; j++)
printf ("%4d", M[i][j]);
printf("\n");
}
return M[n][W];
}
int main()
{
//int val[] = {1, 1, 1};
int W;
int n;
cin >> W >> n;
vector<int> wt(n);
for(int i = 0; i < n; i++){
cin >> wt[i];
}
cout << optimal_weight(W, wt, n) << endl;
}
Thank you for any help!
I figured it out! Here is my solution:
#include <iostream>
#include <vector>
using namespace std;
using std::vector;
int optimal_weight(int W, const vector<int> &wt) {
//write your code here
int n = wt.size();
vector<vector<int> > matrix;
matrix.resize(W+1);
for(int i = 0; i < W+1; i++){
matrix[i].resize(n);
}
for(int j = 0; j < n; j++){
matrix[0][j] = 0;
}
for(int w = 0; w < W + 1; w++){
matrix[w][0] = 0;
}
for(int i = 1; i < n; i++){
for(int w = 1; w < W+1; w++){
matrix[w][i] = matrix[w][i-1];
if(wt[i] <= w){
//cout << wt[i] << endl;
int val = matrix[w-wt[i]][i-1] + wt[i];
if(matrix[w][i] < val){
matrix[w][i] = val;
}
}
}
}
return matrix[W][n-1];
}
int main() {
int n, W;
std::cin >> W >> n;
vector<int> wt(n+1);
for (int i = 1; i < n+1; i++) {
wt[0]=0;
std::cin >> wt[i];
}
std::cout << optimal_weight(W, wt) << '\n';
}
I have the following function to find the parent array in order to obtain a minimum spanning tree of a graph using Prim's algorithm.
#include<stdlib.h>
#include <limits.h>
#include <iostream>
int printMST(int parent[], int n, int** graph)
{
for (int i = 1; i < n; i++)
std::cout<<parent[i]<<" - "<<i<<" "<<graph[i][parent[i]]<<"\n";
}
int* prim(int** graph,int no_of_vertices);
int main(){
int no_of_vertices;
std::cin>>no_of_vertices;
int** graph = new int*[no_of_vertices];
for(int i = 0; i < no_of_vertices; ++i)
graph[i] = new int[no_of_vertices];
for(int i = 0; i <no_of_vertices; ++i)
for(int j = 0; j < no_of_vertices; ++j)
std::cin>>graph[i][j];
int* parent;
parent= prim(graph,no_of_vertices);
// Print the solution
printMST(parent, no_of_vertices, graph);
return 0;
}
int nodeWithMinKey(int key[],bool mst[], int no_of_vertices)
{
int min=1000,min_index;
for(int i=0;i<no_of_vertices;i++)
{
if(mst[i]=false && key[i]<min)
{
min=key[i];
min_index=i;
}
}
return min_index;
}
int* prim(int** graph, int no_of_vertices){
int* parent = (int*)malloc(sizeof(int)*no_of_vertices);
int key[100];
bool mst[100];
int i;
for(i = 0; i<no_of_vertices; i++)
{
key[i] = 1000;
mst[i] = false;
}
key[0] = 0;
parent[0] = -1;
for(i = 0; i<no_of_vertices-1; i++)
{
int u = nodeWithMinKey(key, mst, no_of_vertices);
mst[u] = true;
for(int v = 0; v<no_of_vertices; v++)
{
if(graph[u][v] && mst[v] == false && graph[u][v] < key[v])
{
parent[v] = u;
key[v] = graph[u][v];
}
}
}
return parent;
}
But the parent array is having all the values as '0'(zero), don't know where the condition has gone wrong.
This line
if(mst[i]=false && key[i]<min)
has an assignment = instead of a comparison ==. This will always cause the if test to always fail, so your min_index will never be set.
I'm trying to solve this problem: http://olimpiada-informatica.org/?cmd=downloadE&pbm=velo101&ext=pdf It is in spanish but I will try to translate it here:
You are about to land on earth when you find out that someone has released some Velociraptors in the landing strip.
The landing trip has a rectangular shape. We mark with a dot (.)an empty spot, with a V the velociraptors and with a # the spots with obstacles on them (you cannot land on them).
It takes a second to the velociraptors to go to another spot, but they can only move horizontally and vertically.
You are asked to mark with an X those spots in which, landing on them, you would maximize your remaining lifetime.
I have done an algorithm in which I take every position of the velociraptors and make a BFS on every position, but I'm getting TLE, here is my code:
http://ideone.com/a6BVv3
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <utility>
using namespace std;
int cost[501][501],xx,yy,n,m;
char mat[501][501];
bool visit[501][501],first = true;
int a[] = {-1,0,0,1}, b[] = {0,-1,1,0};
void check(int x,int y,int level) {
cost[x][y] = level;
for(int i = 0; i < 4; ++i) {
xx = x + a[i];
yy = y + b[i];
if(0 <= xx and xx < n and 0 <= yy and yy < m and mat[xx][yy] == '.') {
if(!visit[xx][yy] or level + 1 < cost[xx][yy]) {
visit[xx][yy] = true;
check(xx,yy,level + 1);
}
}
}
}
int max() {
int r = -1;
for(int i = 0; i < n; ++i) for(int j = 0; j < m; ++j) if(mat[i][j] == '.') r = max(r,cost[i][j]);
return r;
}
void show() {
if(!first) puts("---");
int r = max();
for(int i = 0; i < n; ++i) {
for(int j = 0; j < m; ++j) {
if(cost[i][j] == r) printf("X");
else printf("%c",mat[i][j]);
}
puts("");
}
}
int main() {
while(scanf("%d %d",&n,&m) == 2) {
queue<pair<int,int> > cola;
for(int i = 0; i < n; ++i) {
scanf("\n");
for(int j = 0; j < m; ++j) {
scanf("%c",&mat[i][j]);
if(mat[i][j] == 'V') cola.push(make_pair(i,j));
}
}
memset(cost,-1,sizeof cost);
memset(visit,0,sizeof visit);
while(!cola.empty()) {
pair<int,int> aux = cola.front();
visit[aux.first][aux.second] = true;
check(aux.first, aux.second,0);
cola.pop();
}
show();
first = false;
}
return 0;
}
Does anyone know how could I improve my algorithm?
EDIT
Ok, I was able to solve the problem, here is the code if anyone is interested:
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <utility>
using namespace std;
int cost[501][501],n,m;
char mat[501][501];
bool visit[501][501],first = true;
queue<pair<int,int> > cola;
int a[] = {-1,0,0,1}, b[] = {0,-1,1,0};
int max() {
int r = -1;
for(int i = 0; i < n; ++i) for(int j = 0; j < m; ++j) if(mat[i][j] == '.') r = max(r,cost[i][j]);
return r;
}
void show() {
if(!first) puts("---");
int r = max();
for(int i = 0; i < n; ++i) {
for(int j = 0; j < m; ++j) {
if(cost[i][j] == r) printf("X");
else printf("%c",mat[i][j]);
}
puts("");
}
}
int main() {
int cont = 0,x,y,xx,yy,level;
while(scanf("%d %d",&n,&m) == 2) {
for(int i = 0; i < n; ++i) {
scanf("\n");
for(int j = 0; j < m; ++j) {
scanf("%c",&mat[i][j]);
if(mat[i][j] == 'V') cola.push(make_pair(i,j));
}
}
memset(cost,-1,sizeof cost);
memset(visit,0,sizeof visit);
while(!cola.empty()) {
int s_cola = cola.size();
for(int i = 0; i < s_cola; ++i) {
x = cola.front().first, y = cola.front().second;
cola.pop();
level = cost[x][y];
for(int i = 0; i < 4; ++i) {
xx = x + a[i], yy = y + b[i];
if(0 <= xx and xx < n and 0 <= yy and yy < m and mat[xx][yy] == '.') {
if(!visit[xx][yy] or level + 1 < cost[xx][yy]) {
visit[xx][yy] = true;
cost[xx][yy] = level + 1;
cola.push(make_pair(xx,yy));
}
}
}
}
}
show();
first = false;
}
return 0;
}
You're doing a depth-first search of the whole graph in check(). Integrate that with the loop in main() instead of trying to find shortest paths depth-first.