Skip to content

Commit c05bfdc

Browse files
committed
Added some graph Algorithms
1 parent 8d30ebf commit c05bfdc

14 files changed

+645
-0
lines changed

Graph/articulationPoints.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
void Graph::traversalArt(int root,int cur,int src,int id,int &outEC,vector<bool> &isArt){
3+
if(src==root) outEC++;
4+
visited[cur]=true;
5+
lowLink[cur]=ids[cur]=id++;
6+
7+
for(int child:G[cur]){
8+
if(src==child) continue;
9+
if(!visited[child]){
10+
traversalArt(root,child,cur,id,outEC,isArt);
11+
lowLink[cur]=min(lowLink[cur],lowLink[child]);
12+
if(ids[cur]<=lowLink[child])
13+
isArt[cur]=true;
14+
}
15+
else
16+
lowLink[cur] = min(lowLink[cur],ids[child]);
17+
}
18+
}
19+
20+
vector<bool> Graph::findArticulationPoints(){
21+
22+
vector<bool> isArt(numOfNodes+1,false);
23+
visited.resize(numOfNodes+1,false);
24+
lowLink.resize(numOfNodes+1);
25+
ids.resize(numOfNodes+1);
26+
int outEdgeCount;
27+
28+
for(int i=1;i<=numOfNodes;i++){
29+
if(visited[i]) continue;
30+
outEdgeCount=0;
31+
traversalArt(i,i,-1,0,outEdgeCount,isArt);
32+
isArt[i] = (outEdgeCount>1);
33+
}
34+
for(int node=1;node<=numOfNodes;node++)
35+
if(isArt[node]) cout<<" "<<node;
36+
cout<<"\n";
37+
return isArt;
38+
}

Graph/bellmanFord.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
vector<ll> Graph::bellmanFord(int startingNode){
3+
vector<ll> dist(numOfNodes+1,INF);
4+
int V=numOfNodes;
5+
dist[startingNode]=0;
6+
7+
for(int i=0;i<V-1;i++){
8+
for(auto edge:edgeW){
9+
int from=edge.first.first, to=edge.first.second;
10+
ll wt=edge.second;
11+
if(dist[to]>dist[from]+wt)
12+
dist[to]= dist[from]+wt;
13+
}
14+
}
15+
16+
for(int i=0;i<V-1;i++){
17+
for(auto edge:edgeW){
18+
int from=edge.first.first, to=edge.first.second;
19+
ll wt=edge.second;
20+
if(dist[to]>dist[from]+wt){
21+
dist[to]=-1*INF;
22+
}
23+
}
24+
}
25+
/*
26+
for(int node=1;node<=numOfNodes;node++){
27+
cout<<"\n"<<node<<": ";
28+
if(dist[node]<=-1*INF)
29+
cout<<"-INF ";
30+
else cout<<dist[node];
31+
}
32+
cout<<"\n";
33+
*/
34+
return dist;
35+
}

Graph/bfs.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
vector<int> Graph::bfs(int node){
3+
vector<int> prev(numOfNodes+1,-1);
4+
visited.resize(numOfNodes+1,false);
5+
6+
queue<int> q;
7+
q.push(node);
8+
visited[node]=true;
9+
10+
while(!q.empty()){
11+
node = q.front(); q.pop();
12+
for(int child:G[node]){
13+
if(!visited[child]){
14+
q.push(child);
15+
visited[child]=true;
16+
prev[child]=node;
17+
}
18+
}
19+
}
20+
return prev;
21+
}
22+
23+
//To get the path from StartingNode to lastNode
24+
vector<int> Graph::reconstructPathFromBFS(
25+
vector<int> prev, int startingNode, int endingNode){
26+
27+
vector<int> path; //To store the path
28+
29+
int ind=endingNode;
30+
path.push_back(endingNode);
31+
while(prev[ind]!=-1){
32+
path.push_back(prev[ind]);
33+
ind = prev[ind];
34+
}
35+
reverse(path.begin(), path.end());
36+
if(path[0]==startingNode) return path;
37+
else return {-1};
38+
}

Graph/bridge.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
void Graph::traversal(int cur, int par, int val,
3+
vector<pair<int,int> > &bridges){
4+
visited[cur] = true;
5+
lowLink[cur] = ids[cur] = val++;
6+
7+
for(int child:G[cur]){
8+
if(child==par) continue;
9+
if(!visited[child]){
10+
traversal(child,cur,val,bridges);
11+
lowLink[cur] = min(lowLink[child],lowLink[cur]);
12+
if(ids[cur] < lowLink[child])
13+
bridges.push_back({cur,child});
14+
}
15+
else
16+
lowLink[cur] = min(lowLink[cur],ids[child]);
17+
}
18+
}
19+
20+
vector<pair<int,int> > Graph::findBridges(){
21+
22+
ids.resize(numOfNodes+1);
23+
lowLink.resize(numOfNodes+1);
24+
vector<pair<int,int> > bridges;
25+
visited.resize(numOfNodes+1,false);
26+
27+
for(int node=1;node<=numOfNodes;node++){
28+
if(visited[node]) continue;
29+
traversal(node,-1,0,bridges);
30+
}
31+
for(auto bridge:bridges){
32+
cout<<bridge.first<<" "<<bridge.second<<"\n";
33+
}
34+
return bridges;
35+
}

Graph/dfs.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//Time Complexity - O(N)
2+
void Graph::dfsUtil(int node,int src){
3+
cout<<" "<<node;
4+
visited[node]=true;
5+
6+
for(int child:G[node]){
7+
if(child==src) continue;
8+
dfsUtil(child,node);
9+
}
10+
}
11+
12+
//Considering Disconnected Graph as well
13+
int Graph::dfs(int node){
14+
int connectedComponents = 0;
15+
visited.resize(numOfNodes+1,false);
16+
17+
//Considering Disconnected Graph as well
18+
for(int i=1;i<=numOfNodes;i++){
19+
if(visited[i]) continue;
20+
connectedComponents++;
21+
dfsUtil(i,-1);
22+
}
23+
24+
//returns the number of connected components
25+
return connectedComponents;
26+
}

Graph/dijkstra.cpp

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
vector<vector<ll> > Graph::lazyDijkstra(int startingNode){
3+
visited.resize(numOfNodes+1,false);
4+
vector<ll> dist(numOfNodes+1,1e18+1);
5+
vector<ll> prev(numOfNodes+1,-1);
6+
priority_queue<pil,vector<pil>,comparePILByWeight> pq;
7+
8+
pq.push({startingNode,0LL});
9+
dist[startingNode]=0LL;
10+
while(!pq.empty()){
11+
auto cur = pq.top(); pq.pop();
12+
int curNode = cur.first; ll wt = cur.second;
13+
14+
if(dist[curNode]<wt) continue;
15+
visited[curNode]=true;
16+
17+
for(int child:G[curNode]){
18+
if(visited[child]) continue;
19+
ll newDist = dist[curNode]+
20+
edgeW[{min(curNode,child),max(curNode,child)}];
21+
if(newDist<dist[child]){
22+
dist[child]= newDist;
23+
prev[child]= curNode;
24+
pq.push({child,newDist});
25+
}
26+
}
27+
}
28+
//for(int i=1;i<=numOfNodes;i++)
29+
// cout<<i<<" "<<dist[i]<<"\n";
30+
return {dist,prev};
31+
}

Graph/eulerPath.cpp

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
2+
3+
4+
bool Graph::hasEulerianPath(vector<int> &in, vector<int> &out){
5+
int inNodes=0, edNodes=0;
6+
for(int i=1;i<=numOfNodes;i++){
7+
out[i]=G[i].size();
8+
for(int child:G[i])
9+
in[child]++;
10+
}
11+
12+
for(int i=1;i<=numOfNodes;i++){
13+
if(out[i]-in[i]>1 || in[i]-out[i]>1) return false;
14+
if(out[i]-in[i]==1) inNodes++;
15+
else if(in[i]-out[i]==1) edNodes++;
16+
}
17+
return ( (inNodes==0 && edNodes==0) ||
18+
(inNodes==1 && edNodes==1) );
19+
}
20+
21+
int Graph::findStartingNode(vector<int> in, vector<int> out){
22+
int startingNode = 0;
23+
for(int i=1;i<=numOfNodes;i++){
24+
if(out[i]-in[i]==1) return i;
25+
if(out[i]) startingNode=i;
26+
}
27+
return startingNode;
28+
}
29+
30+
int Graph::findEndingNode(vector<int> in, vector<int> out){
31+
int endingNode = 0;
32+
for(int i=1;i<=numOfNodes;i++){
33+
if(in[i]-out[i]==1) return i;
34+
if(in[i]) endingNode=i;
35+
}
36+
return endingNode;
37+
}
38+
39+
void Graph::eulerianTraversal(int cur, vector<int> &path, vector<int> &order){
40+
//cout<<" "<<cur;
41+
order[cur]++;
42+
if(order[cur]>G[cur].size()) return;
43+
eulerianTraversal(G[cur][order[cur]-1], path, order);
44+
45+
path.push_back(cur);
46+
}
47+
48+
void Graph::eulerPath(){
49+
vector<int> path;
50+
vector<int> inDegree(numOfNodes+1,0);
51+
vector<int> outDegree(numOfNodes+1,0);
52+
vector<int> order(numOfNodes+1,0);
53+
54+
bool isPath = hasEulerianPath(inDegree,outDegree);
55+
cout<<"\nisPath: "<<isPath<<"\n";
56+
57+
if(!isPath){ cout<<"\nNo Eulerian Path!\n";return;}
58+
59+
int st = findStartingNode(inDegree,outDegree);
60+
int ed = findEndingNode(inDegree,outDegree);
61+
cout<<"\nstartingNode: "<<st;
62+
eulerianTraversal(st, path, order);
63+
cout<<"\nendingNode: "<<ed;
64+
65+
66+
reverse(path.begin(),path.end());
67+
path.push_back(ed);
68+
69+
//Make sure the graph is not disconnected
70+
if(path.size() != numOfEdges+1){
71+
cout<<"\nGraph is disconnected!!!\n";
72+
return;
73+
}
74+
cout<<"\nPath is: ";
75+
for(int node:path) cout<<" "<<node;
76+
}

Graph/floydWarshall.cpp

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
2+
void Graph::propogateNegativeCycles(vector<vector<ll> > &dp, vector<vector<int> >&next){
3+
int V = numOfNodes;
4+
for(int k=1;k<=V;k++){
5+
for(int i=1;i<=V;i++){
6+
for(int j=1;j<=V;j++){
7+
if(dp[i][k]+dp[k][j]<dp[i][j]){
8+
dp[i][j] = -INF;
9+
next[i][j] = -1;
10+
}
11+
}
12+
}
13+
}
14+
}
15+
16+
// O(V*V*V)
17+
vector<vector<ll> > Graph::floydWarshall(){
18+
int V=numOfNodes;
19+
vector<vector<ll> > dp(V+1,vector<ll>(V+1,INF));
20+
vector<vector<int> > next(V+1,vector<int>(V+1,-1));
21+
22+
for(int i=1;i<=V;i++)
23+
dp[i][i]=0LL;
24+
for(auto edge:edgeW){
25+
int from=edge.first.first, to=edge.first.second;
26+
ll wt = edge.second;
27+
dp[from][to] = wt;
28+
next[from][to] = to;
29+
}
30+
31+
for(int k=1;k<=V;k++){
32+
for(int i=1;i<=V;i++){
33+
for(int j=1;j<=V;j++){
34+
if(dp[i][k]+dp[k][j]<dp[i][j]){
35+
dp[i][j] = dp[i][k]+dp[k][j];
36+
next[i][j] = next[i][k];
37+
}
38+
}
39+
}
40+
}
41+
42+
// propogateNegativeCycles(dp,next);
43+
for(int i=1;i<=V;i++){
44+
for(int j=1;j<=V;j++){
45+
if(dp[i][j]<=-INF) cout<<"-INF ";
46+
else if(dp[i][j]>=INF) cout<<"NP ";
47+
else cout<<dp[i][j]<<" ";
48+
}
49+
cout<<"\n";
50+
}
51+
return dp;
52+
}

Graph/getPath.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
vector<int> Graph::getPath(vector<vector<ll> > dist,
3+
int startingNode, int endingNode){
4+
vector<int> path;
5+
while(endingNode!=-1){
6+
//cout<<endingNode<<"\n";
7+
path.push_back(endingNode);
8+
endingNode = dist[1][endingNode];
9+
}
10+
reverse(path.begin(),path.end());
11+
if(path[0]!=startingNode) return {-1};
12+
else return path;
13+
}

0 commit comments

Comments
 (0)