How to find largest bi-partite subgraph in the given graph? - c++

Given an undirected unweighted graph : it may be cyclic and each vertex has given value ,as shown in image.
Find the size of largest Bi-Partite sub-graph (Largest means maximum number of vertices (connected) in that graph) ?
Answer:
The largest graph is the orange-coloured one, so the answer is 8.
My approach:
#define loop(i,n) for(int i=0;i<n;i++)
int vis[N+1];
vector<int> adj[N+1] // graph in adjacency vector list
int dfs(int current_vertex,int parent,int original_value,int other_value){
int ans=0;
vis[current_vertex]=1; // mark as visited
// map for adding values from neighbours having same value
map<int,int> mp;
// if curr vertex has value original_value then look for the neighbours
// having value as other,but if other is not defined define it
if(value[current_vertex]==original_value){
loop(i,adj[current_vertex].size()){
int v=adj[current_vertex][i];
if(v==parent)continue;
if(!vis[v]){
if(value[v]==other_value){
mp[value[v]]+=dfs(v,current_vertex,original,other);
}
else if(other==-1){
mp[value[v]]+=dfs(v,current_vertex,original,value[v]);
}
}
}
}
//else if the current_vertex has other value than look for original_value
else{
loop(i,adj[current_vertex].size()){
int v=adj[current_vertex][i];
if(v==p)continue;
if(!vis[v]){
if(value[v]==original){
mp[value[v]]+=dfs(v,current_vertex,original,other);
}
}
}
}
// find maximum length that can be found from neighbours of curr_vertex
map<int,int> ::iterator ir=mp.begin();
while(ir!=mp.end()){
ans=max(ans,ir->second);
ir++;
}
return ans+1;
}
calling :
// N is the number of vertices in original graph : n=|V|
for(int i=0;i<N;i++){
ans=max(ans,dfs(i,-1,value[i],-1);
memset(vis,0,sizeof(vis));
}
But I'd like to improve this to run in O(|V|+|E|) time. |V| is the number of veritces and |E| is the number of edges and How do I do that?

This doesn't seem hard. Traverse the edge list and add each one to a multimap keyed by vertex label canonical pairs (the 1,2,3 in your diagram, e.g. with the lowest vertex label value first in the pair).
Now for each value in the multimap - which is a list of edges - accumulate the corresponding vertex set.
The biggest vertex set corresponds to the edges of the biggest bipartite graph.
This algorithm traverses each edge twice, doing a fixed number of map and set operations per edge. So its amortized run time and space is indeed O(|V|+|E|).
Note that it's probably simpler to implement this algorithm with an adjacency list representation than with a matrix because the list gives the edge explicitly. The matrix requires a more careful traversal (like a DFS) to avoid Omega(|V|^2) performance.

Related

create pairs of vertices using adjacency list in linear time

I have n number of vertices numbered 1...n and want to pair every vertex with all other vertices. That would result in n*(n-1)/2 number of edges. Each vertex has some strength.The difference between the strength of two vertices is the weight of the edge.I need to get the total weight. Using two loops I can do this in O(n^2) time. But I want to reduce the time.I can use adjacency list and using that create a graph of n*(n-1)/2 edges but how will I create the adjacency list without using two loops. The input takes only the number of vertices and the strength of each vertex.
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
{
int w=abs((strength[i]-strength[j]));
sum+=w;
}
this is what i did earlier.I need a better way to do this.
If there are O(N*N) edges, then you can't list them all in linear time.
However, if indeed all you need is to compute the sum, here's a solution in O(N*log(N)). You can kind of improve the solution by using instead O(N) sorting algorithm, such as radix sort.
#include <algorithm>
#include <cstdint>
// ...
std::sort(strength, strength+n);
uint64_t sum = 0;
int64_t runSum = strength[0];
for(int i=1; i<n; i++) {
sum += int64_t(i)*strength[i] - runSum;
runSum += strength[i];
}
// Now "sum" contains the sum of weigths over all edges
To explain the algorithm:
The idea is to avoid summing over all edges explicitly (requiring O(N*N)), but rather to add sums of several weights at once. Consider the last vertex n-1 and the average A[n-1] = (strength[0] + strength[1] + ... + strength[n-2])/(n-1): obviously we could add (strength[n-1] - A[n-1]) * (n-1), i.e. n-1 weights at once, if the weights were all larger than strength[n-1], or all smaller than it. However, due to abs operation, we would have to add different amounts depending on whether the strength of the other vertex is larger or smaller than the strength of the current vertex. So one solution is to sort the strengths first, so to ensure that each next strength is greater or equal to the previous.

What is the most efficient way to get all subtrees from node array and edge vector?

Assume that there are nodes as array and undirected edges as vector like this:
int nodes[n] = {1, 2, 3, ... ,n };
vector<pair<int, int>> edges;
edges.push_back(std::make_pair(0, 2));
edges.push_back(std::make_pair(2, 4));
where each element of array is value and nis the number of array. Following above code, there are two edges. One is from 0 to 2. The other one is from 2 to 4. These numbers indicate index of array. In this case, size of largest sub-tree is 3 that 0-2-4 and size of smallest sub-tree is 1 obviously.
I solved this like below:
Sort edges vector
Choose one permutation in edges
Repeat 2 until exploring all possible cases
However I am not sure this is efficient way.
How can I get all sub-trees in the problem domain like this? is there any general and efficient way?
I solved this problem using BFS (Breadth First Search) based on edge information. To avoid making cyclic graph and keep nodes as tree, I use set. And I also apply sort before searching. It is useful to reduce time complexity.
void BFS(set<int> nodes, vector<pair<int,int>>& edges, vector<set<int>>& result) {
result.push_back(nodes);
int lastNode = *max_element(nodes.begin(), nodes.end());
auto findIt = find_if(edges.begin(), edges.end(), [](const pair<int, int>& element){ return element.first == lastNode});
if(findIt != edges.end()) {
nodes.insert((*findIt).second);
BFS(nodes, edges, result);
}
}
sort(edges.begin(), edges.end());
vector<set<int>> result;
for(auto it : edges) {
set<int> nodes;
nodes.insert((*it).first);
nodes.insert((*it).second);
BFS(nodes, edges, result);
}

C++ creating a graph out of dot coordinates and finding MST

I'm trying to make a program in which the user inputs n dot coordinates, 0 < n <= 100. Supposedly, the dots have to be connected, lets say, with ink in a way that you can get e.g from point A to point X while following the inked line and using the least amount of ink possible.
I thought of using Prim Algorithm or something like that to get the MST but for that I need a graph. In all the webpages I've looked they don't really explain that, they always already have the graph with its edges already in there.
I need help specifically creating a graph in C++ out of a bunch of (x, y) coordinates, like the user inputs:
0 0
4 4
4 0
0 4
Please note I'm just starting with C++ and that I can't use any weird libraries since this would be for a page like CodeForces where you only get to use the native libraries.
(For the ones that are also doing this and are here for help, the correct output for this input would be 12)
To assume a complete graph may be most appropriate as suggested by "Beta".
Following code may creates edges between every pair of two dots from a list of dots in the array dots and returns the number of edges created.
After execute this code, you may be able to apply Prim Algorithm for finding MST.
// Definition of Structure "node" and an array to store inputs
typedef struct node {
int x; // x-cordinate of dot
int y; // y-cordinate of dot
} dots[100];
// Definition of Structure "edge"
typedef struct edge {
int t1; // index of dot in dots[] for an end.
int t2; // index of dot in dots[] for another end.
float weight; // weight (geometric distance between two ends)
} lines[];
// Function to create edges of complete graph from an array of nodes.
// Argument: number of nodes stored in the array dots.
// ReturnValue: number of edges created.
// Assumption: the array lines is large enough to store all edges of complete graph
int createCompleteGraph(int numberOfNodes){
int i,j,k,x-diff,y-diff;
k=0; // k is index of array lines
for (i=0; i<numberOfNodes-1; i++) {// index of a node at one end
for (j=i+1; j<numberOfNodes; j++) {// index of a node at another end
lines[k].t1 = i;
lines[k].t2 = j;
x-diff = dots[i].x - dots[j].x;
y-diff = dots[i].y - dots[j].y;
lines[k].weight = sqrt(x-diff * x-diff + y-diff * y-diff) // calculate geometric distance
k++;
}
}
return k;
}

C++ : Storing weight for larger Graph

I was solving some question on graph. It requires to store weight for N Nodes(N<=50000). I cant use matrix to store weight of graph(as 50000x50000 can't be allocated). Do you know any other way? Thanks.
My preferred way of storing not too dense graphs is using adjacency lists.
The downside using adjacency lists is however that you can't directly check if node i is connected to node j. Instead you traverse all neighbors of node i (in which j would eventually show up if it is connected with node i). Also it's not practical to remove edges. I use it when doing breadth-first or depth-first searches on a graph, since one is only interested in the set of neighbors and not whether two specific nodes are connected.
In summary:
Takes only as much memory as you have edges (which is what you wanted) but at least as much memory as you have nodes.
Easy to traverse egdes for any node, i.e. always constant time per neighbor
To check whether two nodes i and j are connected you need to traverse the whole neighborhoodlist of node i or j. Which is bad if one node is connected to almost all other nodes and cheap if its connected to a few
Removing edges is also expensive for large neighborhoods (at worst linear time in the number of neighbors of a node) and cheap for small neighborhoods.
Inserting edges is very cheap (constant time)
To give you an example (first with all weights 1)
using Graph = std::vector<std::vector<int>>;
now you can create a graph with n nodes with:
Graph mygraph(n);
And if you want to connect node i and j just do
mygraph[i].push_back(j);
mygraph[j].push_back(i);
And to traverse all edges of some node, you can simply do
for (int neighbor : mygraph[i]) {
std::cout << i << " is connected with " << neighbor << std::endl;
}
And now for the harder problem with general weights:
using Graph = std::vector<std::vector<std::pair<int, double>>>;
Graph myWeightedgraph(n);
Now you can insert edges very easily
double weight = 123.32424;
myWeightedgraph[i].push_back({j, w});
myWeightedgraph[j].push_back({i, w});
And for traversal:
for (auto& neighbor : myWeightedgraph[i]) {
std::cout << i << " is connected with " << neighbor.first << " with weight " << neighbor.second << std::endl;
}
If two nodes can't have multiple edges between them:
First think of some system how to give each existing edge an unique number.
Eg. for N nodes and node numbers netween 0 and N-1, a edge between node A and node B could simply have A*N+B (eg. in an uint64_t variable)
Then make a std::map of edges, with the calculated number as key and the weight as value. Most operations there have logarithmic time, which is not as good than the 2D array but still good, and you need much less memory.
There are generally two ways to represent graphs. As you stated, the first one is to use an adjacency matrix. The pros are that you can easily see if two nodes i and j are connected. The downside is the space complexity (O(V²) where V is the number of vertices).
The other one is the adjacency list: for each vertex, you store an adjacency list that contains every edge coming out of that vertex. Obviously, the spatial complexity is O(V + E) where V is the number of vertices and E the number of edges.
Note that you can store the edges in adjacency maps instead of lists. Let's say you give each edge a unique integer key. If your graph is sparse, an std::unordered_map would fit well since collisions odds will be low. This grants you on average O(1) lookup and insertion complexity for a given edge.
If your graph can have a huge number of edges, then just use a regular std::map which relies on red black trees. You'll then have a logarithmic complexity for both inserting or looking up a node.
Here is some sample code:
struct Edge {
int weight;
int start, end;
}
struct Vertex {
int key;
std::unordered_map<int, Edge> adjacency_map;
}
struct Graph {
std::vector<Edge> edges;
}
You can't allocate an array with size of orders 10^9 as a static memory. You should be using malloc instead. Better still, you can use adjacency list to store the graph.

Find distance from a node to the one farthest from it BOOST

I need to fin the distance from all nodes to the node farthest from it in the minimum spanning tree. I have done this so far but I got no clue as to find the longest distance from a node.
#include<iostream>
#include<boost/config.hpp>
#include<boost/graph/adjacency_list.hpp>
#include<boost/graph/kruskal_min_spanning_tree.hpp>
#include<boost/graph/prim_minimum_spanning_tree.hpp>
using namespace std;
using namespace boost;
int main()
{
typedef adjacency_list< vecS, vecS, undirectedS, property <vertex_distance_t,int>, property< edge_weight_t, int> > Graph;
int test=0,m,a,b,c,w,d,i,no_v,no_e,arr_w[100],arr_d[100];
cin>>test;
m=0;
while(m!=test)
{
cin>>no_v>>no_e;
Graph g(no_v);
property_map <Graph, edge_weight_t>:: type weightMap=get(edge_weight,g);
bool bol;
graph_traits<Graph>::edge_descriptor ed;
for(i=0;i<no_e;i++)
{
cin>>a>>b>>c;
tie(ed,bol)=add_edge(a,b,g);
weightMap[ed]=c;
}
property_map<Graph,edge_weight_t>::type weightM=get(edge_weight,g);
property_map<Graph,vertex_distance_t>::type distanceMap=get(vertex_distance,g);
property_map<Graph,vertex_index_t>::type indexMap=get(vertex_index,g);
vector< graph_traits<Graph>::edge_descriptor> spanning_tree;
kruskal_minimum_spanning_tree(g,back_inserter(spanning_tree));
vector<graph_traits<Graph>::vector_descriptor>p(no_v);
prim_minimum_spanning_tree(g,0,&p[0],distancemap,weightMap,indexMap,default_dijkstra_visitor());
w=0;
for(vector<graph_traits<Graph>::edge_descriptor>::iterator eb=spanning_tree.begin();eb!=spanning_tree.end();++eb) //spanning tree weight
{
w=w+weightM[*eb];
}
arr_w[m]=w;
d=0;
graph_traits<Graph>::vertex_iterator vb,ve;
for(tie(vb,ve)=vertices(g),.
arr_d[m]=d;
m++;
}
for( i=0;i<test;i++)
{
cout<<arr_w[i]<<endl;
}
return 0;
}
If i have a spanning tree with nodes 1 2 3 4 I need to find longest distance from 1 2 3 4 in the spanning tree(and the longest distance can comprise of many edges not only one).
I'll not give you exact code how to do this but I'll give you and idea how to do this.
First, result of MST (minimum spanning tree) is so called tree. Think about the definition. One can say it is a graph where exists path from every node to every other nodes and there are no cycles. Alternatively you can say that given graph is a tree iff exists exactly one path from vertex u to v for every u and v.
According to the definition you can define following
function DFS_Farthest (Vertex u, Vertices P)
begin
define farthest is 0
define P0 as empty set
add u to P
foreach v from neighbours of u and v is not in P do
begin
( len, Ps ) = DFS_Farthest(v, P)
if L(u, v) + len > farthest then
begin
P0 is Ps union P
farthest is len + L(u, v)
end
end
return (farthest, P0)
end
Then you'll for every vertex v in graph call DFS_Farthest(v, empty set) and it'll give you (farthest, P) where farthest is distance of the farthest node and P is set of vertices from which you can reconstruct the path from v to farthest vertex.
So now to describe what is it doing. First the signature. First parameter is from what vertex you want to know farthest one. Second parameter is a set of banned vertices. So it says "Hey, give me the longest path from v to farthest vertex so the vertices from P are not in that path".
Next there is this foreach thing. There you are looking for farthest vertices from current vertex without visiting vertices already in P (current vertex is already there). When you find path longer then currently found not it to farthest and P0. Note that L(u, v) is length of the edge {u, v}.
At the end you'll return those length and banned vertices (this is the path to the farthest vertex).
This is just simple DFS (depth first search) algorithm where you remember already visited vertices.
Now about time complexity. Suppose you can get neighbours of given vertex in O(1) (depends on data structure you have). Function visits every vertex exactly once. So it is at least O(N). To know farthest vertex from every vertex you have to call this function for every vertex. This gives you time complexity of this solution of your's problem at least O(n^2).
My guess is that better solution might be done using dynamic programming but this is just a guess. Generally finding longest path in graph is NP-hard problem. This makes me suspicious that there might not me any significantly better solution. But it's another guess.