A universal sink is a vertex which has no edge emanating from it, and all other vertices have an edge towards the sink. Determine whether a universal sink exists in a directed graph
Example:
Input:
Output: Sink found at vertex 2
Input:
Output: No Sink
Adjacency Matrix Elimination Approach - O(V^2) Time and O(V^2) Space
Instead of examining each vertex one by one, we can efficiently eliminate non-sink vertices by using the adjacency matrix.
We begin with the first vertex (i = 0) and the first column (j = 0) and traverse the matrix following simple rules: if adj[i][j] == 1, it means vertex i cannot be a sink, so we increment i; if adj[i][j] == 0, it means vertex j cannot be a sink, so we increment j.
This process continues until either i or j exceeds the total number of vertices, leaving only one candidate vertex. Finally, we verify this candidate by checking that its row contains all 0s and its column contains all 1s except for the diagonal element to confirm whether it is indeed a universal sink.
Example: Consider the graph
Step 1: Create adjacency matrix
Step 2: Eliminate non-sink vertices
Start with i = 0 and j = 0.
Rules:
If adj[i][j] equals 1, vertex i cannot be a sink since it has an outgoing edge to j, so increment i.
If adj[i][j] equals 0, vertex j cannot be a sink since it is missing an incoming edge from i, so increment j.
Iteration:
i=0, j=0, adj[0][0]=0, increment j to j=1
i=0, j=1, adj[0][1]=1, increment i to i=1
i=1, j=1, adj[1][1]=0, increment j to j=2
i=1, j=2, adj[1][2]=0, increment j to j=3
i=1, j=3, adj[1][3]=0, increment j to j=4
i=1, j=4, adj[1][4]=0, increment j to j=5
i=1, j=5, adj[1][5]=0, increment j to j=6
j exceeds number of vertices - stop scanning. Candidate sink = vertex 1 (0-based index), which is vertex 2 in 1-based indexing.
Step 3: Verify candidate sink
Row of v2 - all 0s
Column of v2 - all 1s except diagonal
v2 is the universal sink.
C++
usingnamespacestd;// Function to check if vertex i is a universal sinkboolisSink(vector<vector<int>>&adj,inti){intV=adj.size();for(intj=0;j<V;j++){// Row should be all 0sif(adj[i][j]==1)returnfalse;// Column should be all 1s except diagonalif(adj[j][i]==0&&j!=i)returnfalse;}returntrue;}// Function to find the universal sink by eliminationintfindSink(vector<vector<int>>&adj){intV=adj.size();inti=0,j=0;while(i<V&&j<V){if(adj[i][j]==1)// Row i cannot be sinki++;else// Column j cannot be sinkj++;}// Check if the found sink is validif(i>=V||!isSink(adj,i))return-1;// Candidate sink (0-based index)returni;}// Function to add a directed edge from i to jvoidaddEdge(vector<vector<int>>&adj,inti,intj){adj[i][j]=1;}intmain(){intV=6;vector<vector<int>>adj(V,vector<int>(V,0));// Add directed edgesaddEdge(adj,0,1);// v1 -> v2addEdge(adj,2,1);// v3 -> v2addEdge(adj,3,1);// v4 -> v2addEdge(adj,4,1);// v5 -> v2addEdge(adj,5,1);// v6 -> v2intsink=findSink(adj);if(sink>=0)cout<<"Sink found at vertex "<<(sink+1)<<endl;elsecout<<"No Sink"<<endl;return0;}
Java
importjava.util.ArrayList;publicclassGFG{// Function to check if vertex i is a universal sinkstaticbooleanis_sink(ArrayList<ArrayList<Integer>>adj,inti){intV=adj.size();for(intj=0;j<V;j++){// Row should be all 0sif(adj.get(i).get(j)==1)returnfalse;// Column should be all 1s except diagonalif(adj.get(j).get(i)==0&&j!=i)returnfalse;}returntrue;}// Function to find the universal sink by eliminationstaticintfindSink(ArrayList<ArrayList<Integer>>adj){intV=adj.size();inti=0,j=0;while(i<V&&j<V){if(adj.get(i).get(j)==1)// Row i cannot be sinki++;else// Column j cannot be sinkj++;}if(i>=V||!is_sink(adj,i))// No sink existsreturn-1;// Candidate sink (0-based index)returni;}// Function to add a directed edge from i to jstaticvoidaddEdge(ArrayList<ArrayList<Integer>>adj,inti,intj){adj.get(i).set(j,1);}publicstaticvoidmain(String[]args){intV=6;ArrayList<ArrayList<Integer>>adj=newArrayList<>();// Initialize adjacency matrix with 0for(inti=0;i<V;i++){ArrayList<Integer>row=newArrayList<>();for(intj=0;j<V;j++)row.add(0);adj.add(row);}// Add directed edgesaddEdge(adj,0,1);addEdge(adj,2,1);addEdge(adj,3,1);addEdge(adj,4,1);addEdge(adj,5,1);intsink=findSink(adj);if(sink>=0)System.out.println("Sink found at vertex "+(sink+1));elseSystem.out.println("No Sink");}}
Python
# Function to check if vertex i is a universal sinkdefis_sink(adj,i):V=len(adj)forjinrange(V):# Row should be all 0sifadj[i][j]==1:returnFalse# Column should be all 1s except diagonalifadj[j][i]==0andj!=i:returnFalsereturnTrue# Function to find the universal sink by eliminationdeffindSink(adj):V=len(adj)i=j=0whilei<Vandj<V:ifadj[i][j]==1:# Row i cannot be sinki+=1else:# Column j cannot be sinkj+=1ifi>=Vornotis_sink(adj,i):# No sink existsreturn-1# Candidate sink (0-based index)returni# Function to add a directed edge from i to jdefaddEdge(adj,i,j):adj[i][j]=1if__name__=="__main__":V=6adj=[[0for_inrange(V)]for_inrange(V)]# Add directed edgesaddEdge(adj,0,1)addEdge(adj,2,1)addEdge(adj,3,1)addEdge(adj,4,1)addEdge(adj,5,1)sink=findSink(adj)ifsink>=0:print("Sink found at vertex",sink+1)else:print("No Sink")
C#
usingSystem;classGFG{// Function to check if vertex i is a universal sinkstaticboolis_sink(int[,]adj,inti){intV=adj.GetLength(0);for(intj=0;j<V;j++){// Row should be all 0sif(adj[i,j]==1)returnfalse;// Column should be all 1s except diagonalif(adj[j,i]==0&&j!=i)returnfalse;}returntrue;}// Function to find the universal sink by eliminationstaticintfindSink(int[,]adj){intV=adj.GetLength(0);inti=0,j=0;while(i<V&&j<V){if(adj[i,j]==1)// Row i cannot be sinki++;else// Column j cannot be sinkj++;}if(i>=V||!is_sink(adj,i))// No sink existsreturn-1;// Candidate sink (0-based index)returni;}// Function to add a directed edge from i to jstaticvoidaddEdge(int[,]adj,inti,intj){adj[i,j]=1;}publicstaticvoidMain(String[]args){intV=6;int[,]adj=newint[V,V];// Add directed edgesaddEdge(adj,0,1);addEdge(adj,2,1);addEdge(adj,3,1);addEdge(adj,4,1);addEdge(adj,5,1);intsink=findSink(adj);if(sink>=0)Console.WriteLine("Sink found at vertex "+(sink+1));elseConsole.WriteLine("No Sink");}}
JavaScript
// Function to check if vertex i is a universal sinkfunctionis_sink(adj,i){letV=adj.length;for(letj=0;j<V;j++){// Row should be all 0sif(adj[i][j]===1)returnfalse;// Column should be all 1s except diagonalif(adj[j][i]===0&&j!==i)returnfalse;}returntrue;}// Function to find the universal sink by eliminationfunctionfindSink(adj){letV=adj.length;leti=0,j=0;while(i<V&&j<V){if(adj[i][j]===1){// Row i cannot be sinki++;}else{// Column j cannot be sinkj++;}}if(i>=V||!is_sink(adj,i))// No sink existsreturn-1;// Candidate sink (0-based index)returni;}// Function to add a directed edge from i to jfunctionaddEdge(adj,i,j){adj[i][j]=1;}// driver codeletV=6;letadj=Array.from({length:V},()=>Array(V).fill(0));// Add directed edgesaddEdge(adj,0,1);addEdge(adj,2,1);addEdge(adj,3,1);addEdge(adj,4,1);addEdge(adj,5,1);letsink=findSink(adj);if(sink>=0)console.log("Sink found at vertex "+(sink+1));elseconsole.log("No Sink");
Output
Sink found at vertex 2
There exist better approaches to solve this problem. Please refer The Celebrity Problem for more efficient approaches.