Exceeding time limit for bipartite graph problem - c++

I am solving Bipartite graph problem on Coursera.
Actual problem statement is as follows:
I am using BFS to find if the given graph is bipartite or not but the grader is showing "time exceeded".
#include<bits/stdc++.h>
using namespace std;
int BFS(vector<vector<int>> &adList,int s,int n,set<int> &visited)
{
#define inf 0
vector<int> color(n+1,inf);
color[s]=-1;
visited.erase(s);
queue<int> Q;
Q.push(s);
while(!Q.empty())
{
int u=Q.front();
Q.pop();
for(int v:adList[u])
{
if(color[v]==inf)//if unvisited
{
visited.erase(v);
Q.push(v);
color[v]=color[u]*-1;
}
else
{
if((color[v]*color[u])>0)
return 0;
}
}
}
return 1;
}
int connectedComp(vector<vector<int>> &adList,int m,int n)
{
set<int> visited;
for(int i=1;i<=n;++i)
{
visited.insert(i);
}
int val;
while(!visited.empty())
{
int i=(*(visited.front()));
val=BFS(adList,i,n,visited);
if(!val)
return 0;
}
return 1;
}
int main()
{
int n,m;
cin>>n>>m;
vector<vector<int>> adList(n+1,vector<int>(0));
for(int i=1;i<=m;++i)
{
int s,d;
cin>>s>>d;
adList[s].push_back(d);
adList[d].push_back(s);
}
int val=connectedComp(adList,m,n);
cout<<val;
}
According to me complexity for this code should be O(|E|+|V|) but it still times out.
Failed case #17/27: time limit exceeded (Time used: 3.98/2.00, memory used: 42123264/536870912.)
I have gone through GFG but there also exists a same approach for this problem.

Related

Find max cost edge between two nodes in tree

Task:
Given a weighted tree graph and a set of nodes pairs. For each pair (u,v) from set I need to find(effectively) maximum edge between (u,v).
My approach:
Using Tarjan's algoritm for each pair (u,v) we can find lowest common ancestor LCA(u,v) = a. Then we can present the path between (u,v) as union of (u,a) and (v,a) pathes and maximum edge between (u,v) as max(max_edge(u,a),max_edge(v,a)).
Problem:
I'm trying to add max_edge save in LCA algoritm, but haven't got any success yet.
The question is: How can I add support of max edge save at LCA Tarjan's algorithm?
My attempt code:
int max_cost;
int dsu_find(int node)
{
if (node == parent[node])
return node;
max_cost = std::max(max_cost, edges[node][parent[node]]);
return parent[node] = dsu_find(parent[node]);
}
void lca_dfs(int node, std::vector<std::list<int>> &query_list)
{
dsu_make(node);
ancestor[node] = node;
marks[node] = true;
for(auto neighbour:adjacency_list[node])
{
if (!marks[neighbour.first])
{
lca_dfs(neighbour.first,query_list);
dsu_unite(node, neighbour.first);
ancestor[dsu_find(node)] = node;
}
}
for (auto query_node : query_list[node])
if (marks[query_node])
{
dsu_find(query_node);
dsu_find(node);
printf("%d %d -> %lld\n", node, query_node,max_cost);
query_list[query_node].remove(node);
max_cost = 0;
}
}
But it's working incorrect.
My full lca implementation(without incorrect modifications):
std::vector<int> parent;
std::vector<int> rank;
std::vector<int> ancestor;
std::vector<bool> marks;
std::vector<std::list<std::pair<int, long long>>> adjacency_list;
void lca_dfs(int node, std::vector<std::list<int>> &query_list)
{
dsu_make(node);
ancestor[node] = node;
marks[node] = true;
for(auto neighbour:adjacency_list[node])
{
if (!marks[neighbour.first])
{
lca_dfs(neighbour.first,query_list);
dsu_unite(node, neighbour.first);
ancestor[dsu_find(node)] = node;
}
}
for (auto query_node : query_list[node])
if (marks[query_node])
{
printf("LCA of %d %d is %d\n", node, query_node,ancestor[dsu_find(query_node)]);
query_list[query_node].remove(node);
}
}
//dsu operations
void dsu_make(int node)
{
parent[node] = node;
rank[node] = 0;
}
int dsu_find(int node)
{
return node == parent[node] ? node : parent[node]=dsu_find(parent[node]);
}
void dsu_unite(int node_1,int node_2)
{
int root_1 = dsu_find(node_1), root_2 = dsu_find(node_2);
if(root_1!=root_2)
{
if(rank[root_1] < rank[root_2])
std::swap(root_1, root_2);
parent[root_2] = root_1;
if (rank[root_1] == rank[root_2])
rank[root_1]++;
}
}
*For each node query_list[node] consists of v such as (node,v) is needed pair.
I understood, that I using double memory(just for easier access).
I'll be gratefull for any hints or implementation fixes.
Hope this Implementation works for you.
#include <bits/stdc++.h>
#include <algorithm>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ass 1e18
#define MOD 1000000007
#define mp make_pair
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define fi first
#define se second
#define sz(x) (ll)x.size()
#define present(c,x) ((c).find(x) != (c).end())
#define boost ios_base::sync_with_stdio(false);cin.tie(NULL);
#define debug(x) cout << #x << ": " << x << endl;
#define debug2(x,y) cout<<#x<<": "<< x<< ", "<< #y<< ": "<< y<< endl;
#define debug3(x,y,z) cout<<#x<<": "<< x<< ", "<< #y<< ": "<< y<<" "<<#z<<" : "<<z<< endl;
using namespace std;
typedef long long int ll;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
pair<int,int> parent[200005],par[200005],dpp[200005][19];
vector<pair< pair<int,int>,pair<int,int> > >v;
vector<pair<int,int> >vv[200005];
int level[200005],vis[200005];
ll ans[200005];
void dfs(int x,int p)
{
level[x]=level[p]+1;
for(int i=0;i<sz(vv[x]);i++)
{
if(vv[x][i].fi!=p)
{
par[vv[x][i].fi].fi=x;
par[vv[x][i].fi].se=vv[x][i].se;
dfs(vv[x][i].fi,x);
}
}
}
void computeparent(int n)
{
for(int i=1;i<=n;i++)
dpp[i][0]=par[i];
for(int j=1;j<=18;j++)
{
for(int i=1;i<=n;i++)
{
dpp[i][j].fi=dpp[dpp[i][j-1].fi][j-1].fi;
dpp[i][j].se=max(dpp[i][j-1].se,dpp[dpp[i][j-1].fi][j-1].se);
}
}
}
int lca(int a,int b)
{
if(level[b]>level[a])
swap(a,b);
int diff=level[a]-level[b];
int m=ceil(log2(diff));
for(int i=m;i>=0;i--)
{
if(diff&(1LL<<i))
a=dpp[a][i].fi;
}
if(a==b)
return a;
for(int i=m;i>=0;i--)
{
if(dpp[a][i].fi!=dpp[b][i].fi)
{
a=dpp[a][i].fi;
b=dpp[b][i].fi;
}
}
return dpp[a][0].fi;
}
int lca2(int a,int b)
{
int c=a,d=b;
if(level[b]>level[a])
swap(a,b);
int i,maxi=0,diff=level[a]-level[b];
int m=ceil(log2(diff));
for(int i=m;i>=0;i--)
{
if(diff&(1LL<<i))
{
maxi=max(maxi,dpp[a][i].se);
a=dpp[a][i].fi;
}
}
return maxi;
}
int finds(int a)
{
while(parent[a].fi!=a)
{
a=parent[a].fi;
}
return a;
}
void unions(int x,int y)
{
if(parent[x].se>parent[y].se)
parent[y].fi=x;
else if(parent[x].se<parent[y].se)
parent[x].fi=y;
else
{
parent[x].fi=y;
parent[x].se++;
}
}
void solve()
{
ll sum=0;
int n,m,i,a,b,c;
cin>>n>>m;
for(i=1;i<=n;i++)
{
parent[i].fi=i;
parent[i].se=0;
}
for(i=0;i<m;i++)
{
cin>>a>>b>>c;
v.pb(mp(mp(c,i),mp(a,b)));
}
sort(v.begin(),v.end());
for(i=0;i<sz(v);i++)
{
int a=v[i].se.fi,b=v[i].se.se;
int x=finds(a),y=finds(b);
if(x!=y)
{
vv[a].pb(mp(b,v[i].fi.fi));
vv[b].pb(mp(a,v[i].fi.fi));
ans[v[i].fi.se]=1;
unions(x,y);
sum+=v[i].fi.fi;
}
}
dfs(1,0);
computeparent(n);
for(i=0;i<m;i++)
{
if(ans[v[i].fi.se]==0)
{
int a=lca(v[i].se.fi,v[i].se.se);
ans[v[i].fi.se]=sum+v[i].fi.fi-max(lca2(a,v[i].se.fi),lca2(a,v[i].se.se));
}
else
ans[v[i].fi.se]=sum;
}
for(i=0;i<m;i++)
cout<<ans[i]<<"\n";
}
int main()
{
boost
int t=1;
//cin>>t;
while(t--)
{
solve();
}
return 0;
}

Track level of nodes in a graph and print level for each node

I want to traverse a graph using BFS algorithm and want to track the nodes by their level.
Here is my code.
#include<iostream>
#include<queue>
#include<vector>
#include<stdlib.h>
using namespace std;
int main()
{
int edges,a,b;
vector<int>nodes[1000];
cout<<"Enter the no of edges"<<endl;
cin>>edges;
for(int i=0; i<edges; i++)
{
cin>>a>>b;
nodes[a].push_back(b);
nodes[b].push_back(a);
}
cout<<endl;
queue<int> que;
//initially que is empty
bool visited[1000];
int level[1000];
// mark all the vertices as not visited
for(int i=0; i<1000; i++)
{
visited[i]=false;
}
int start;
cout<<"\nEnter the starting node"<<endl;
cin>>start;
//insert the starting node into the queue
que.push(start);
level[start]=1;
//mark the starting node as visited
visited[start]=true;
cout<<"\nBFS Traversal\n";
while(!que.empty())
{
//Dequeue a vertex from que and print it
int front = que.front();
cout<<front<<" ";
que.pop();
// get all adjacent vertices of the dequeued vertex s
// If an adjacent vertex has not been visited,
//then mark it as visited
// and enqueue it
for(vector<int>::iterator it=nodes[front].begin();
it!=nodes[front].end(); ++it)
{
if(visited[*it]==false)
{
visited[*it]=true;
que.push(*it);
}
}
// cout<<endl;
}
cout<<endl;
int Sz = sizeof(level)/sizeof(int);
/*for(int i=0;i<=edges;i++)
{
cout<<"Level of "<<i<<"is "<<level[10]<<endl;
}*/
return 0;
}
[please notice the commented out portion at the end of the code.I tried some ways but failed.I removed those tracking.Please help me updating the code.]
You can use this function to find the level of each node in the tree.
Complexity is O(n) since we are visiting each node once.
Best of Luck
#define ll long long int
ll level[100005],arr[100005];
vector <ll> adj[100005];
void bfs(ll s)
{
ll vis[100005];
memset(vis,false,sizeof vis);
queue <ll> q;
q.push(s);
level[s] = 1;
vis[s] = true;
while(!q.empty())
{
ll p = q.front();
//cout<<p<<endl;
q.pop();
vector <ll>::iterator it;
for(it=adj[p].begin();it!=adj[p].end();++it)
{
if(vis[*it] == false)
{
level[*it] = level[p] + 1;
q.push(*it);
vis[*it] = true;
}
}
}
}

Wrong Answer http://www.spoj.com/problems/WORDS1/

I have written the following code for the above problem.
I have checked if Graph is connected by choosing the start node and doing DFS from it. And checking the conditions for Euler path and tour, in code that would be count= 2 or 0. It's working on all given test cases.But getting wrong answer on submission
#include<iostream>
#include<cmath>
#include<list>
#include<string>
#include<stack>
using namespace std;
class Graph
{
int V;
list<int> *adj;
int *in;
public:
Graph(int v)
{
this->V=v;
this->adj=new list<int>[V];
this->in=new int[V];
for(int i=0;i<V;i++)
{
in[i]=0;
}
}
void addEdge(int src,int des)
{
adj[src].push_back(des);
in[des]=in[des]+1;
}
void DFSUtil(bool visited[],int v)
{
stack<int> s;
s.push(v);
visited[v]=true; //mark v as visited;
while (!s.empty())
{
int top=s.top();
s.pop();
list<int> :: iterator it;
for(it=adj[top].begin();it!=adj[top].end();it++)
{
if(!visited[*it])
{
visited[*it]=true;
s.push(*it);
}
}
}
}
/*void DFSUtil(bool visited[],int v)
{
visited[v]=true;
list<int> :: iterator it;
for(it=adj[v].begin();it!=adj[v].end();it++)
{
if(!visited[*it])
{
DFSUtil(visited,*it);
}
}
}*/
// Graph reverseGraph()
// {
// Graph g(V);
// for(int i=0;i<V;i++)
// {
// list<int> :: iterator it;
// for(it=adj[i].begin();it!=adj[i].end();it++)
// {
// g.addEdge(*it,i);
// }
// }
// return g;
// }
bool isConnected()
{
//bool visited[V];
bool* visited=new bool[V];
for(int i=0;i<V;i++)
visited[i]=false;
int i=0;
int flag=0;
int n;
for(i=0;i<V;i++)
{
if(adj[i].size()>0)
{
n=i;
flag=1;
}
if(((int)adj[i].size()-in[i])==1 && in[i]==0) //selecting the start vertex i.e vertex with no incoming edges
{
n=i;
break;
}
}
if(i==V&&flag==0)
return 0;
DFSUtil(visited,n); //dfs to check if every node is reachable fro start vertex
for(int i=0;i<V;i++)
{
if(visited[i]==false && adj[i].size()>0)
return 0;
}
// Graph gr=reverseGraph();
// for(int i=0;i<V;i++)
// visited[i]=false;
// gr.DFSUtil(visited,n);
// for(int i=0;i<V;i++)
// {
// if(visited[i]==false && adj[i].size()>0)
// return 0;
// }
return 1;
}
bool isEuler()
{
int count=0;
int magnitude;
for(int i=0;i<V;i++) //check conditions on in and out edges, out edges=adj[].size
{
magnitude=in[i]-(int)adj[i].size();
if(magnitude<0)
magnitude=magnitude*-1;
if((magnitude)==1)
{
count=count+1;
}
else if(in[i]!=adj[i].size())
{
return 0;
}
}
if(count==1 || count>2)
return 0;
if(isConnected()==0) //check if graph is connected
return 0;
return 1;
}
};
int main()
{
int t;
//scanf("%d",&t);
cin>>t;
while(t--)
{
int n;
//scanf("%d",&n);
cin>>n;
string str;
if(n==1) //only one string entered
{
cin>>str;
cout<<"Ordering is possible.\n";
continue;
}
Graph g(26);
int src,des;
for(int i=0;i<n;i++)
{
cin>>str;
src=str[0]-'a';
des=str[str.length()-1]-'a';
g.addEdge(src,des);
}
if(g.isEuler())
{
cout<<"Ordering is possible.\n";
}
else
{
cout<<"The door cannot be opened.\n";
}
}
}
In your function isConnected, you attempt to find the start vertex with no incoming edges by breaking out of the for loop upon a certain condition. If this condition is not encountered, the loop variable i will contain the value 26, rather than an expected index in the range 0..25. When the value 26 is passed to the DFSUtil function it will caused an out of bounds array access. I get a crash on the line visited[v] = true;
A condition that will cause this to arise, is the test case from the linked site with the repeated word:
2
ok
ok
Your check to find the start vertex does not handle this case well.

TLE in codeforces's Dijkstra

I just learnt Dijkstra's algorithm and solved a few problems and I am trying to solve this http://codeforces.com/problemset/problem/20/C problem but I am getting Time limit Exceeded in a large test case, I want to know if my code can be further optimized in any way or if there is any other faster implementation of Dijkstra then let me know.
My code
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define vp vector<pii>
int p[100010],d[100010];
void printer(int current)
{
if(p[current]==-2)
{
printf("%d ",current);
return;
}
printer(p[current]);
printf("%d ",current);
}
class Prioritize
{
public:
int operator()(const pii &p1,const pii &p2)
{
return p1.second<p2.second;
}
};
int main()
{
priority_queue<pii, vp, Prioritize> Q;
int nv;
scanf("%d",&nv);
vp g[nv+1];
int ne,u,v,w;
scanf("%d",&ne);
for(int i=0;i<ne;i++)
{
scanf("%d %d %d",&u,&v,&w);
g[u].push_back(pii(v,w));
g[v].push_back(pii(u,w));
}
int source=1;
int size;
for(int i=1;i<=nv;i++)
{
d[i]=INT_MAX;
p[i]=-1;
}
d[source]=0;
p[source]=-2;//marker for source.
Q.push(pii(source,d[source]));
while(!Q.empty())
{
u=Q.top().first;
Q.pop();
size=g[u].size();
for(int i=0;i<size;i++)
{
v=g[u][i].first;
w=g[u][i].second;
if(d[v]>d[u]+w)
{
d[v]=d[u]+w;
p[v]=u;
Q.push(pii(v,d[v]));
}
}
}
/*for(int i=1;i<=nv;i++)
{
printf("Node %d and min weight = %d and parent = %d\n",i,d[i],p[i]);
}*/
if(p[nv]==-1)
{
printf("%d\n",-1);
return 0;
}
printer(nv);
return 0;
}
Your algorithm has complexity O(nm). I propose to add the following
Q.push(pii(source,d[source]));
while(!Q.empty())
{
u=Q.top().first;
int curD = Q.top().second; //this
if( curD > d[u]) continue; //and this
Q.pop();
size=g[u].size();
for(int i=0;i<size;i++)
{
After changes complexity will be O(mlogn). If you now russian you can read http://e-maxx.ru/algo/dijkstra_sparse

SIGABRT Error during runtime (c++)

This is the skyscraper floors problem from spoj. I m getting SIGABRT when I run the code.Link for the problem is http://www.spoj.com/problems/SCRAPER/. When I run this code on my PC, it runs without any error but spoj's online judge shows SIGABRT error.
#include <iostream>
#include <vector>
using namespace std;
struct floor
{
unsigned int floornum;
bool calldone;
vector <floor*> connection;
floor()
{
floornum=0;
calldone=0;
}
};
struct elevator
{
unsigned int x,y;
elevator()
{
x=y=0;
}
};
struct skyscrapper
{
unsigned int f,e,a,b;
vector <elevator> ele;
vector <floor*> flooraddress; //this is a spoj problem
void read()
{
cin>>f>>e>>a>>b;
elevator *temp;
for(unsigned int i=0;i<e;i++)
{
temp=new elevator;
cin>>(*temp).x>>(*temp).y;
ele.push_back(*temp);
}
for (unsigned int i=0;i<f;i++)
{
floor* tempp=new floor;
(*tempp).floornum=i;
flooraddress.push_back(tempp);
}
}
void allotaddress()
{
unsigned int j,k;
for(unsigned int i=0;i<ele.size();i++)
{
j=ele[i].y;
k=ele[i].x;
while(j<f)
{
if(j!=ele[i].y)
{
(*(flooraddress[j])).connection.push_back(flooraddress[j-k]);
(*(flooraddress[j-k])).connection.push_back(flooraddress[j]);
}
j=j+k;
}
}
}
};
bool flag;
bool traverse(floor* m,int destination)
{
if((*m).calldone==1)
{
return 0;
}
(*m).calldone=1;
if((*m).floornum==destination)
return 1;
if((*m).connection.empty())
return 0;
for(int i=0;i<(*m).connection.size();i++)
{
flag=traverse(((*m).connection[i]),destination);
if(flag==1)
return flag;
}
return 0;
}
int main()
{
int n;
cin>>n;
skyscrapper iit[n];
bool ans[n];
for(int i=0;i<n;i++)
{
iit[i].read();
iit[i].allotaddress();
ans[i]=traverse(iit[i].flooraddress[iit[i].a],iit[i].b);
}
for(int i=0;i<n;i++)
{
if(ans[i]==1)
cout<<"It is possible to move the furniture."<<endl;
else
cout<<"The furniture cannot be moved."<<endl;
}
return 0;
}