0% found this document useful (0 votes)
37 views39 pages

Harmans C++ Specifics

Uploaded by

h.singh.ultra
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
37 views39 pages

Harmans C++ Specifics

Uploaded by

h.singh.ultra
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 39

HERE ARE THE BEST CHEATSHEETS:

https://leetcode.com/discuss/study-guide/1154632/C%2B%2B-STL-powerful-guide-or-
Compiled-list-of-popular-STL-operations
https://leetcode.com/discuss/study-guide/1359115/All-C%2B%2B-STL-internal-
implementation-oror-last_minute_notes-oror-2021

###################################################################
1) USING TREESETS AND TREE MAPS C++

Round 1
Design a data structure with two operations 1. addRange(int start, int end)
and 2. contains(int point)
Here range means an interval, so the data structure contains information
of all ranges added uptil that point and you can have interleaved queries
of the form contains(int point) which returns true if the point
is contained in any of the ranges or false otherwise.

The solution I thought of was to store the ranges/intervals as a


list of sorted disjoint intervals (i.e merge overlapping intervals).
Now when we get a contains query, we can perform binary
search(interval with start point equal to or less than point)
to find a potential interval that may contain it. addRange would
be O(n) and contains would be O(logn). I believe there is a better
solution with interval trees but interviewer said this solution
was okay which I ended up coding.

USE sortedcontainers in python or


Q1:
Use a treemap => amortized O(logn) merge and O(logn) contains.

STL map is inherently a binary search tree - just use map::find.


Using container member functions, where they are present,
is preferable to algorithms.

How to find all elements in a range in STL map(set)

If you are using std::map, it's already sorted, your


can use lower_bound/upper_bound an example from cplusplus.com:

// map::lower_bound/upper_bound
#include <iostream>
#include <map>

int main ()
{
std::map<char,int> mymap;
std::map<char,int>::iterator itlow,itup;

mymap['a']=20;
mymap['b']=40;
mymap['c']=60;
mymap['d']=80;
mymap['e']=100;

itlow=mymap.lower_bound ('b'); // itlow points to b


itup=mymap.upper_bound ('d'); // itup points to e (not d!)
mymap.erase(itlow,itup); // erases [itlow,itup)

// print content:
for (std::map<char,int>::iterator it=mymap.begin(); it!=mymap.end(); ++it)
std::cout << it->first << " => " << it->second << '\n';

return 0;
}

1.5) MULTIMAP USAGE + DELETE lowerbound and upperbound

#include <iostream>
#include <map>
using namespace std;

int main (){


multimap<string, string> MyMMap;
multimap<string, string>::iterator it, itlower, itupper;

MyMMap.insert(pair<string, string>("CAN", "Toronto"));


MyMMap.insert(pair<string, string>("IND", "Delhi"));
MyMMap.insert(pair<string, string>("JPN", "Tokyo"));
MyMMap.insert(pair<string, string>("USA", "New York"));
MyMMap.insert(pair<string, string>("USA", "Washington"));

itlower = MyMMap.lower_bound("CAN");
itupper = MyMMap.upper_bound("JPN");
MyMMap.erase(itlower, itupper);

cout<<"MyMMap contains: \n ";


for(it = MyMMap.begin(); it != MyMMap.end(); ++it)
cout<<it->first<<" "<<it->second<<"\n ";
return 0;
}

Output
MyMMap contains:
USA New York
USA Washington

2) Binary Search C++

Binary search is an important component in competitive programming


or any algorithmic competition, having knowledge of shorthand functions
reduces the time to code them. This searching only works when container
is sorted. Related functions are discussed below.
####
1.binary_search(start_ptr, end_ptr, num) : This function returns
boolean true if the element is present in the container, else returns false.

// C++ code to demonstrate the working of binary_search()

#include<bits/stdc++.h>
using namespace std;
int main()
{
// initializing vector of integers
vector<int> arr = {10, 15, 20, 25, 30, 35};

// using binary_search to check if 15 exists


if (binary_search(arr.begin(), arr.end(), 15))
cout << "15 exists in vector";
else
cout << "15 does not exist";

cout << endl;

// using binary_search to check if 23 exists


if (binary_search(arr.begin(), arr.end(), 23))
cout << "23 exists in vector";
else
cout << "23 does not exist";

cout << endl;


}

Output:
15 exists in vector
23 does not exist

#####
2. lower_bound(start_ptr, end_ptr, num) : Returns pointer to
“position of num” if container contains 1 occurrence of num.
Returns pointer to “first position of num” if container contains
multiple occurrence of num. Returns pointer to “position of next higher
number than num” if container does not contain occurrence of num.
Subtracting the pointer to 1st position i.e “vect.begin()” returns the actual
index.

// C++ code to demonstrate the working of lower_bound()


#include<bits/stdc++.h>
using namespace std;

int main()
{
// initializing vector of integers
// for single occurrence
vector<int> arr1 = {10, 15, 20, 25, 30, 35};

// initializing vector of integers


// for multiple occurrences
vector<int> arr2 = {10, 15, 20, 20, 25, 30, 35};

// initializing vector of integers


// for no occurrence
vector<int> arr3 = {10, 15, 25, 30, 35};

// using lower_bound() to check if 20 exists


// single occurrence
// prints 2
cout << "The position of 20 using lower_bound "
" (in single occurrence case) : ";
cout << lower_bound(arr1.begin(), arr1.end(), 20)
- arr1.begin();

cout << endl;

// using lower_bound() to check if 20 exists


// multiple occurrence
// prints 2
cout << "The position of 20 using lower_bound "
"(in multiple occurrence case) : ";
cout << lower_bound(arr2.begin(), arr2.end(), 20)
- arr2.begin();

cout << endl;

// using lower_bound() to check if 20 exists


// no occurrence
// prints 2 ( index of next higher)
cout << "The position of 20 using lower_bound "
"(in no occurrence case) : ";
cout << lower_bound(arr3.begin(), arr3.end(), 20)
- arr3.begin();

cout << endl;


}
Output:

The position of 20 using lower_bound (in single occurrence case) : 2


The position of 20 using lower_bound (in multiple occurrence case) : 2
The position of 20 using lower_bound (in no occurrence case) : 2

#####
3. upper_bound(start_ptr, end_ptr, num) : Returns pointer to
“position of next higher number than num” if container
contains 1 occurrence of num. Returns pointer to “first position of next
higher number than last occurrence of num” if container contains
multiple occurrence of num. Returns pointer to “position of next
higher number than num” if container does not contain occurrence of num.
Subtracting the pointer to 1st position i.e “vect.begin()” returns the actual
index.

// C++ code to demonstrate the working of upper_bound()


#include<bits/stdc++.h>
using namespace std;

int main()
{
// initializing vector of integers
// for single occurrence
vector<int> arr1 = {10, 15, 20, 25, 30, 35};

// initializing vector of integers


// for multiple occurrences
vector<int> arr2 = {10, 15, 20, 20, 25, 30, 35};

// initializing vector of integers


// for no occurrence
vector<int> arr3 = {10, 15, 25, 30, 35};
// using upper_bound() to check if 20 exists
// single occurrence
// prints 3
cout << "The position of 20 using upper_bound"
" (in single occurrence case) : ";
cout << upper_bound(arr1.begin(), arr1.end(), 20)
- arr1.begin();

cout << endl;

// using upper_bound() to check if 20 exists


// multiple occurrence
// prints 4
cout << "The position of 20 using upper_bound "
"(in multiple occurrence case) : ";
cout << upper_bound(arr2.begin(), arr2.end(), 20)
- arr2.begin();

cout << endl;

// using upper_bound() to check if 20 exists


// no occurrence
// prints 2 ( index of next higher)
cout << "The position of 20 using upper_bound"
" (in no occurrence case) : ";
cout << upper_bound(arr3.begin(), arr3.end(), 20)
- arr3.begin();

cout << endl;


}
Output:

The position of 20 using upper_bound (in single occurrence case) : 3


The position of 20 using upper_bound (in multiple occurrence case) : 4
The position of 20 using upper_bound (in no occurrence case) : 2

3) MAP VS MULTIMAP AND USING COMPARATORS TO BUILD RED BLACK TREE IN MAP:
std::map takes up to four template type arguments,
the third one being a comparator. E.g.:

struct cmpByStringLength {
bool operator()(const std::string& a, const std::string& b) const {
return a.length() < b.length();
}
};

// ...
std::map<std::string, std::string, cmpByStringLength> myMap;
Alternatively you could also pass a comparator to maps constructor.

Note however that when comparing by length you can


only have one string of each length in the map as a key.

note that we can use multimap if we want to contain duplicated key


Since C++11, you can also use a lambda expression
instead of defining a comparator struct:

auto comp = [](const string& a, const string& b) { return a.length() <


b.length(); };
map<string, string, decltype(comp)> my_map(comp);

my_map["1"] = "a";
my_map["three"] = "b";
my_map["two"] = "c";
my_map["fouuur"] = "d";

for(auto const &kv : my_map)


cout << kv.first << endl;

4) Binary Search Algorithm in STL


This function returns Boolean true if the element is present in
the given range, else Boolean false is returned.
There are two variations of binary_search():

binary_search(first, last, value): this version returns true if there is an


element present, satisfying the condition (!(a < value) &&!(value <
a))
in the given range, i.e from first to last, in other words,
operator(<)
is used to check the equality of the two elements.

binary_search(first, last, value, compare_function) :


this version return true if there is an element present
in the given range, i.e from first to the last.

Note that first and last are iterators and the element
pointed by last is excluded from the search.

Here we don't have to first sort element container, binary_search()


will do all the work for us, we just have to
give a range and a value which is to searched.

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

bool compare_string_by_length (string i,string j)


{
return (i.size() == j.size());
}

int main ()
{
int inputs[] = {7,8,4,1,6,5,9,4};
vector<int> v(inputs, inputs+8);

cout<<binary_search(v.begin() , v.end() , 7 ); //prints 1 , Boolean true


cout<<binary_search(v.begin() , v.end() , 217); //prints 0 , Boolean false

/* compare_function can be used to search


non numeric elements based on their properties */

string s[] = { "test" , "abcdf" , "efghijkl" , "pop" };

cout<<binary_search(s, s+4, "nickt" , compare_string_by_length);


/* search for the string in s which have same length as of "nicky" */

5) How to sort a vector but also keep track of indexes C++:

Using C++ 11 lambdas:

#include <iostream>
#include <vector>
#include <numeric> // std::iota
#include <algorithm> // std::sort, std::stable_sort

using namespace std;

template <typename T>


vector<size_t> sort_indexes(const vector<T> &v) {

// initialize original index locations


vector<size_t> idx(v.size());
iota(idx.begin(), idx.end(), 0);

// sort indexes based on comparing values in v


// using std::stable_sort instead of std::sort
// to avoid unnecessary index re-orderings
// when v contains elements of equal values
stable_sort(idx.begin(), idx.end(),
[&v](size_t i1, size_t i2) {return v[i1] < v[i2];});

return idx;
}
Now you can use the returned index vector in iterations such as

for (auto i: sort_indexes(v)) {


cout << v[i] << endl;
}

You can also choose to supply your original index vector,


sort function, comparator, or automatically reorder v
in the sort_indexes function using an extra vector.

share improve this answer follow


edited Feb 2 at 8:02

Guillaume Jacquenot
8,41855 gold badges3737 silver badges4646 bronze badges
answered Sep 13 '12 at 4:10

Łukasz Wiklendt
3,59022 gold badges1515 silver badges1515 bronze badges
4
Love this answer.If your compiler does not support lambdas, you can use a
class: template<typename T> class CompareIndicesByAnotherVectorValues {
std::vector<T>* _values;
public: CompareIndicesByAnotherVectorValues(std::vector<T>* values) :
_values(values)
{}
public: bool operator() (const int& a, const int& b)
const { return (_values)[a] > (_values)[b]; } }; – Yoav Oct 18 '12 at 7:47

6) PRIORITY QUEUE EXAMINATION WITH CUSTOM CLASSES:

Hey guys i want to implement a priority queue which contains entries of type
'node'.
The code is as follows....

struct node
{
int a;
int b;
};

bool cmp(const node& A,const node& B)


{
return (A.a<B.a) || (A.a==B.a && A.b>B.b);
}

/// main function starts

priority_queue<node,vector<node>, cmp> Y;

But i am not able to compile with error... "type/value mismatch at argument 3


in template parameter list for 'template<class _Tp, class _Sequence, class
_Compare>
class std::priority_queue"... Can anyone help me out...

The third template parameter of priority_queue expects a type (_functor_),


not a function. Rather than doing it this way, it's easier to define the
comparison operator inside the struct, then priority_queue will
see it automatically:

struct node
{
int a;
int b;

bool operator <(const node& other) const


{
return (a<other.a) || (a==other.a && b>other.b);
}
};

If you still want to use the functor way, then you should define the functor
class:

struct node
{
int a;
int b;
};

struct cmp
{
bool operator ()(const node& A,const node& B) const
{
return (A.a<B.a) || (A.a==B.a && A.b>B.b);
}
};

. . .
priority_queue<node,vector<node>, cmp> Y;

Member functions
(constructor)
Construct priority queue (public member function )
empty
Test whether container is empty (public member function )
size
Return size (public member function )
top
Access top element (public member function )
push
Insert element (public member function )
emplace
Construct and insert element (public member function )
pop
Remove top element (public member function )
swap
Swap contents (public member function )

USAGE:

7) C++ A Priority Queue USAGE + BINARY TREE MAP USAGE:

1. Find K Pairs with Smallest Sums

You are given two integer arrays nums1 and nums2


sorted in ascending order and an integer k.

Define a pair (u,v) which consists of one element from the first
array and one element from the second array.

Find the k pairs (u1,v1),(u2,v2) ...(uk,vk) with the smallest sums.

Example 1:

Input: nums1 = [1,7,11], nums2 = [2,4,6], k = 3


Output: [[1,2],[1,4],[1,6]]
Explanation: The first 3 pairs are returned from the sequence:
[1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]
Example 2:

Input: nums1 = [1,1,2], nums2 = [1,2,3], k = 2


Output: [1,1],[1,1]
Explanation: The first 2 pairs are returned from the sequence:
[1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3]
Example 3:

Input: nums1 = [1,2], nums2 = [3], k = 3


Output: [1,3],[2,3]
Explanation: All possible pairs are returned from the sequence: [1,3],[2,3]

C++ SOLUTION A (fastest):

class Solution {
public:
vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>&
nums2, int k) {
vector<pair<int,int>> result;
if (nums1.empty() || nums2.empty() || k <= 0)
return result;
auto comp = [&nums1, &nums2](pair<int, int> a, pair<int, int> b) {
return nums1[a.first] + nums2[a.second] > nums1[b.first] +
nums2[b.second];};
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(comp)>
min_heap(comp);
min_heap.emplace(0, 0);
while(k-- > 0 && min_heap.size())
{
auto idx_pair = min_heap.top(); min_heap.pop();
result.emplace_back(nums1[idx_pair.first], nums2[idx_pair.second]);
if (idx_pair.first + 1 < nums1.size())
min_heap.emplace(idx_pair.first + 1, idx_pair.second);
if (idx_pair.first == 0 && idx_pair.second + 1 < nums2.size())
min_heap.emplace(idx_pair.first, idx_pair.second + 1);
}
return result;
}
};

C++ SOLUTION B (slower):

struct compare
{
bool operator() (const pair<int, int> & a, const pair<int, int> & b)
{
return a.first + a.second >= b.first + b.second;
}
};

class Solution {
public:
vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2,
int k) {

if (nums1.empty() || nums2.empty() || k == 0)
return {};

priority_queue< pair<int, int>, vector<pair<int, int>>, compare > que;

int N = nums1.size();
int M = nums2.size();
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
que.push({nums1[i], nums2[j]});
}
}

vector<vector<int>> ans;

int count = min(k, (int)que.size());

for (int s = 0; s < count; s++)


{
auto item = que.top();
que.pop();

ans.push_back({});
ans.back().push_back(item.first);
ans.back().push_back(item.second);
}

return ans;
}
};

class Solution {
public:
vector<vector<int>> kSmallestPairs(vector<int>& v1, vector<int>&v2, int k)
{
map<int,vector<pair<int,int>>>mp;
int sz1=v1.size(),sz2=v2.size();
for(int i=0;i<sz1;++i){
for(int j=0;j<sz2;++j)
mp[v1[i]+v2[j]].push_back({v1[i],v2[j]});
}

vector<vector<int>>res;
for(auto it=mp.begin();it!=mp.end();++it){
for(pair<int,int>p:it->second){
if(res.size()==k)
break;
res.push_back({p.first,p.second});
}
}
return res;
}
};

8) Set erase, can use both element as well as iterator is this for all containers?
// erasing from set
#include <iostream>
#include <set>

int main ()
{
std::set<int> myset;
std::set<int>::iterator it;

// insert some values:


for (int i=1; i<10; i++) myset.insert(i*10); // 10 20 30 40 50 60 70 80 90

it = myset.begin();
++it; // "it" points now to 20

myset.erase (it);

myset.erase (40);

it = myset.find (60);
myset.erase (it, myset.end());

std::cout << "myset contains:";


for (it=myset.begin(); it!=myset.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';

return 0;
}

11) HOW TO SUM ELEMENTS IN C++ VECTOR:

C++11 and higher


b. Automatically keeping track of the vector type even in case of future
changes:

#include <numeric>

sum_of_elems = std::accumulate(vector.begin(), vector.end(),


decltype(vector)::value_type(0));
Using std::for_each:

std::for_each(vector.begin(), vector.end(), [&] (int n) {


sum_of_elems += n;
});
Using a range-based for loop (thanks to Roger Pate):

for (auto& n : vector)


sum_of_elems += n;

10) QUORA TRICKS: (https://www.quora.com/Competitive-Programming/What-are-some-


cool-C++-tricks-to-use-in-a-programming-contest)
I’ve being practicing for ACM ICPC for about one year and I
already gathered some C/C++ tricks that I use in almost every problem:

Loop in C-string:
char s[100];
for (int i = 0; s[i]; ++i) { ... }
This is extremely useful (also avoids the strlen usage, that you
could forget is O(n) and put on for condition).

Testing if not negative 1:


if (~x) { ... }
In competitive programming we tend to write as little as possible,
só a simple x ! = -1 can be shortened to 2 characters.

This works because negative numbers use two’s complement, so -1


is represented as all ones in binary. The tilde (~) operation inverts
all bits of the variable, so the -1 turns into a zero, and any other
number turns into something not zero. The if condition is valid if it’s
not zero, so ~x is valid for any value different than zero.

Least significant 1 bit


int lsb = x&-x;
This is a very useful operation than returns the LSB (EDIT: the least
significant bit with value 1) of a number. If you’re used to Fenwick Tree
(aka Binary Indexed Tree, or just BIT) then you know how useful it is.

This also works because of two’s complement. If you AND any number and it’s
negative you obtain the LSB. Very simple and fast.

More than one operation per line


if (dist[v] > dist[u] + w)
dist[v] = dist[u] + w, q.push(v);

Many people don’t know this, but you can have statements split
by commas. This I tend to use in every problem I solve, it reduces
the code and avoids the use of semicolons.

The only down side is that you can’t use with break, continue or
return (not statements :/). So when I have to use any of these I have
to add braces and semicolons.

Scanf on array
int a[100];
for (int i = 0; i < n; ++i) scanf("%d", a+i);

This I don’t like very much because it doesn’t work for arrays
with higher dimensions, but since most problems have at most 1D
input it’s quite useful too (although I tend to use the &a[i],
but my teammates use this trick).

Order array without losing original order


int a[100], p[100];
// receive input
for (int i = 0; i < n; ++i) scanf("%d", &a[i]), p[i] = i;

sort(p, p+n, [=](int i, int j) { return a[i] < a[j]; });


This is extremely useful!

First you don’t lose the original order (for offline algorithms this can be
necessary).

Second you can do the same for how many dimensions you have
(for 2D points: x[] and y[]; or 3D: x[], y[] and z[]; or any number
of arrays..) and you don’t have to create structures (lot’s of lines saved)
or use tuple or pairs (these are annoying in competitive programming. Using
pair of pair you have something like: x.first.second + x.second.second and
you line goes extra large and hard to read).

Infinite
const int INF = 0x3f3f3f3f;
This infinite constant is very useful too. I used to do something like x = 2e9;
but I had to take care about not adding infinites (because of integer overflow)
and stuff like this. This constant can be doubled without overflowing and also
can be set very easily this way:

int dist[1000];
memset(dist, 63, sizeof(dist)); // 0x3f == 63
For shortest path algorithms I always use this (I used to tend -1 version,
but I had to do additional checks to verify if dist == -1 and if not..)
and in CP BFS and SSSP are very common problems.

I think that’s all for now. If I remember any other trick I’ll edit this
answer,
but that’s all I can remember for now!

###################################################################################
##############################3
Code forces c++ tips and trick: (https://codeforces.com/blog/entry/74684)

C++ tips and tricks

By Golovanov399, 8 months ago, In English


Hello, codeforces.

I would like to tell you about some tricks and constructions I use in C++. They
are not hidden or anything, moreover, most of them are from stl or maybe well known
among software engineers, but I often see codes where something is done by hand in,
say, 5 lines, while in stl there is a function which does the same.

The things below are filtered by my personal sense of non-popularity (so no


__builtin functions) and usage frequency (so there almost surely are similar things
I don't know about) and are not really sorted in any reasonable order. Let's begin.

all(x)
This may be an exception to the rule of non-popularity -- this is quite widely
used, but some next items will depend on all(x), so I define it here. So, I talk
about

#define all(x) (x).begin(), (x).end()


Now sorting a vector looks like sort(all(vec)) instead of sort(vec.begin(),
vec.end()).

However, it's not all about this define. Imagine you need to build a convex
hull of a set of points. Usually the code looks approximately as follows:

vector<Point> getConvexHull(vector<Point> pts) {


int min_pos = min_element(all(pts)) - pts.begin();
swap(pts[0], pts[min_pos]);
sort(pts.begin() + 1, pts.end(), &cmp);
// ...
}
And it might not come to one's mind that pts.begin() + 1 is the same as 1 +
pts.begin(), and hence the code can be rewritten as
vector<Point> getConvexHull(vector<Point> pts) {
int min_pos = min_element(all(pts)) - pts.begin();
swap(pts[0], pts[min_pos]);
sort(1 + all(pts), &cmp);
// ...
}
Be, however, careful with this, because this reduces code readability
significantly. Thanks to my teammates AndreySergunin and white2302 for showing me
this 1 + all(...) trick.

std::unique
This is also well known, but not as well as I want, so I leave it here.
std::unique(begin, end) goes from begin to end, removes consecutive duplicates and
returns the end of the resulting iterator range. So, for example, if vec = {1, 1,
2, 2, 3, 2, 1}, then unique(all(vec)) makes it equal {1, 2, 3, 2, 1, ?, ?} (where ?
is not known, but probably the last two symbols are 2 and 1) and returns
vec.begin() + 5. Usually, to make a vector containing only its unique elements, one
writes

sort(all(vec));
vec.resize(unique(all(vec)) - vec.begin());
or creates a function/define make_unique (which is, actually, also a name of
some existing function in C++) which does so.

nxt()
I noticed that many Kotlin Heroes participants often have some functions in
their templates like readLong(), readToken() and so on. I understand that this may
be for the sake of similarity with C++ paradigm where you can just read stuff or
maybe because val (n, k) = readLine()!!.split(' ').map(String::toInt) is too long
and weird for writing it just to read two numbers. However, what doesn't often come
to mind is that a similar function in C++ can simplify a lot of things (or maybe
it's just a matter of taste). So the function may look as follows:

int nxt() {
int x;
cin >> x;
return x;
}
If a usual reading a graph looks like this:

int n, m;
cin >> n >> m;
for (int i = 0; i < m; ++i) {
int u, v;
cin >> u >> v;
--u, --v;
g[u].push_back(v);
g[v].push_back(u);
}
then with your little mriemd nxt() you can write the following:

int n = nxt(), m = nxt();


for (int i = 0; i < m; ++i) {
int u = nxt() - 1, v = nxt() - 1;
g[u].push_back(v);
g[v].push_back(u);
}
However, be careful! If pts is a vector of points, then it's really better to
read it in the following way:

for (int i = 0; i < (int)pts.size(); ++i) {


cin >> pts[i].x >> pts[i].y;
}
or at least in the following C++17 way:

for (auto& [x, y] : pts) {


cin >> x >> y;
}
But don't do the following:

for (int i = 0; i < (int)pts.size(); ++i) {


pts[i] = {nxt(), nxt()};
}
because in the last implementation the order of nxt() calls is not defined.

Also you may change the type to long long or even make the function template,
but I haven't really ever felt I need the last.

Big thanks to my former teammates savinov and sokian for introducing this to me
in their team template back in 2015 when I joined them. nxt() will return later in
this blog.

std::fill and std::iota


Many of you know that if one wants to fill a piece of memory with a specific
byte, they can use memset. It's quite fast and can be used to fill some (usually 1-
dimensional) C-arrays by zeroes and minus ones. What if you want to fill a
container by ones? The answer is as easy as pie:

fill(all(vec), 1);
And if you need to fill it by consecutive numbers, you can use std::iota. Now
the constructor of a Dsu class with two optimizations may look as follows:

int n;
vector<int> parent, rank;

Dsu(int _n): n(_n), parent(_n), rank(_n) {


iota(all(parent), 0);
}
Here 0 denotes the value of *parent.begin(), and each next value is obtained
from the previous one by the pre-increment.

std::generate
If you have a 0-ary function (that is, with no arguments) and want to fill a
range by its calls, instead of writing a for loop you can call std::generate:
filling a vector vec by random values (assume it's rand() calls) may look like

generate(all(vec), rand);
My favourite: to read n followed by n numbers you can write

int n = nxt();
vector<int> a(n);
generate(all(a), nxt);
or, if you don't need the value of n later, even

vector<int> a(nxt());
generate(all(a), nxt);
Bonus: the last three function have a _n analogs. Instead of the end
iterator/pointer, fill_n, iota_n and generate_n take the size as the second
argument. So if you want to read, say, first n numbers into a vector vec of size
greater than n, you can use

generate_n(vec.begin(), n, nxt);
instead of a longer

generate(vec.begin(), vec.begin() + n, nxt);


Thanks to fdoer for telling this.

std::rotate
Assume you write a profile dp. Or a 3-layer bfs. Or something else, where you
need sometimes to cyclically shift a vector by k. If k=1 then one can write a loop
of swaps:

for (int i = 0; i < (int)vec.size() - 1; ++i) {


swap(vec[i], vec[i + 1]);
}
But if k>1 then the easiest way to do this manually is probably to create
another vector, fill it accordingly and then set the initial vector to this.
However a simple

rotate(vec.begin(), vec.begin() + k, vec.end());


can do the trick. This function works in such a way that after rotate(begin,
middle, end) the element *middle becomes the first from begin to end.

std::merge
If you want to build a segment tree where each node contains a sorted list of
values from the corresponding range then on its initialization you may need to
merge two vectors several times (or if you implement your own merge sort). Some of
you, probably, write some code like this:

for (int v = n - 1; v > 0; --v) {


int i = 0, j = 0;
while (i < (int)nodes[2 * v].size() || j < (int)nodes[2 * v + 1].size()) {
if (j == (int)nodes[2 * v + 1].size() || (i < (int)nodes[2 * v].size()
&& nodes[2 * v][i] < nodes[2 * v + 1][j])) {
nodes[v].push_back(nodes[2 * v][i++]);
} else {
nodes[v].push_back(nodes[2 * v + 1][j++]);
}
}
}
However, this code can be shortened:

for (int v = n - 1; v > 0; --v) {


nodes[v].resize(nodes[2 * v].size() + nodes[2 * v + 1].size());
merge(all(nodes[2 * v]), all(nodes[2 * v + 1]), nodes[v].begin());
}
Basically, std::merge takes 5 arguments: begin and end of one interval to
merge, begin and end of the second interval to merge, and where to write the
result. Don't forget to allocate the required memory (the purpose of .resize() in
the code above)!

Create a set from a vector


Not many of us know, but if you want to create a std::set from a vector and
find out that set doesn't have a constructor of vector, you may go write a loop
with an ok face, like:
set<int> S;
for (int x : a) {
S.insert(x);
}
However, std::set has a constructor of two iterators, so one can write

set<int> S(all(a));
This is actually very natural and one can deduce that set should have such a
constructor, but I, to my shame, didn't know it until white2302 told me this
recently.

Check if set or map have a key


This may be the most well known of above (as well as the least time-saving
trick), but I still see that some experienced guys do the subj like

if (S.find(key) != S.end()) {
// ...
}
However, set and map have a .count() method which returns 1 iff the key is in
the container, otherwise 0:

if (S.count(key)) {
// ...
}
The reason why it is called so and has an int type is that std::multiset and
std::multimap also have this method, and for them the method returns the count of
elements, which may exceed 1, obviously. Thanks to my former students dimas.kovas
and krock21 for enlightening me about this.

Of course, if you need to do something with the element, if it is present in


the set (for example, erase it), it may be useful to actually call .find() method
in order to erase by iterator, not by element (thus kind of caching one tree
descent).

Check if an element occurs in a sorted sequence


Assume that you have, say, a sorted vector, and you want to check if it
contains an element, but unlike the previous case, you don't care about the element
itself. In this case you don't need to implement your own binary search like

bool has(const vector<int>& vec, int key) {


int l = 0, r = vec.size();
while (r > l + 1) {
int m = (l + r) / 2;
if (vec[m] <= key) {
l = m;
} else {
r = m;
}
}
return l + 1 == r && vec[l] == key; // not to fall on the empty vector
}
Instead, you can just use

if (binary_search(all(vec), key)) {
// ...
}
I think the function doesn't need any explanation (it returns bool, so there is
really not much else one can extract from this). Thanks to some guy who used this
method in some easy problem in an SRM.
std::partition_point
If we talk about binary search: assume you have a vector and a predicate p(x)
so that p(x) = true for all elements of some prefix of vector vec and false on all
others. To find the first place where p(x) doesn't hold one can simply use

int pos = partition_point(all(vec), p) - vec.begin();


In other words, partition_point(begin, end, p) returns the first iterator iter
that p(*iter) = false, assuming that the condition above holds, that is, p is true
on some prefix of [begin, end). I didn't use this in competitive programming (yet),
but once wanted to use it for my job. Thanks to fdoer again for sharing his wisdom.

!!
Assume you want to use a function which maps 0 to 0 and every non-zero number
to 1 (for example, to count non-zero numbers on all prefix subrectangles). The most
observant of you may have notices that this is simply a cast to bool. The easiest
bool casting operator is !! and it works like this:

for (int i = 0; i < n; ++i) {


for (int j = 0; j < m; ++j) {
pref[i + 1][j + 1] = pref[i][j + 1] + pref[i + 1][j] - pref[i][j] + !!
a[i][j];
}
}
Afaik, a mnemonic rule to remember it (if needed) is "bang, bang, you're
boolean".

Print a binary representation of a number


If you want to print, say, last 20 bits of a number, it's not necessary to
write smth like

void show_binary(int n) {
for (int i = 0; i < 20; ++i) {
cout << !!(n & (1 << i));
}
cout << "\n";
}
Instead, one can simply write

cout << bitset<20>(n) << "\n";


However, you need to fix the number of bits to show (which is usually not a
problem because in most of the cases you need it for debug purposes) and get used
to the order where the lowest bit is the rightmost (which is actually a natural
order for a binary representation of a number, but not so natural if you consider a
mask as a sort of a boolean vector).

Also, if you want to print an octal or a hexadecimal representation of a


number, you can simply write cout << oct << n << "\n" and cout << hex << n << "\n",
respectively. To return back to normal decimal, use cout << dec.

lambda type deduction


Imagine you want to quickly write a lambda which calculates the number of ways
to choose 2 elements from n. You may write something like this:

auto choose2 = [&](int n) {


if (n <= 1) {
return 0;
} else {
return 1ll * n * (n - 1) / 2;
}
};
and see that the compiler cannot deduce the type of your lambda: in one place
you return int and in another place you return long long. Ok, you may think, let's
show the type explicitly. without auto:

function<long long(int)> choose2 = [&](int n) {


if (n <= 1) {
return 0;
} else {
return 1ll * n * (n - 1) / 2;
}
};
To your surprise, the error doesn't disappear. You are not very happy, you
replace 0 by 0ll and move forward feeling that you could surely have done this
using some language tools.

Indeed, in the very first version you could actually explicitly specify the
output type by a simple arrow:

auto choose2 = [&](int n) -> long long {


if (n <= 1) {
return 0;
} else {
return 1ll * n * (n - 1) / 2;
}
};
Big thanks to my friends and colleagues Wild_Hamster, ArtDitel and fdoer again
for showing me this construction (not only in this context, however).

Introducing variables inside an if statement


Imagine the following: you have a function f(), which takes time to be
computed, and if its value satisfies some condition, you want to somehow use it.
You don't want to write

if (is_good(f())) {
use_somehow(f());
}
since it costs two calls of f. You may write something like this:

int x = f();
if (is_good(x)) {
use_somehow(x);
}
but this is not very clean and leaves a variable which is not used then, maybe
under a potentially useful name. To avoid this, one can wrap all this into a block
like this:

{
int x = f();
if (is_good(x)) {
use_somehow(x);
}
}
but a shorter version would do the following:

if (int x = f(); is_good(x)) {


use_somehow(x);
}
This is possible since C++17.

The smallest element from three


I bet many, many of you at least once wrote something like

int x = min(min(a, b), c);


feeling that something you do in your life is not right (while you type this,
you usually have time to think about such things). Things get worse if you want to
get a minimum of four elements:

int x = min(min(min(a, b), c), d);


(the order or arguments and the way to regroup them does not matter). You may
have written a variadic template in your, well, template, to call something like
min(a, b, c, ...), but you may do this without any prewritten code. Just watch:

int x = min({a, b, c, d});


Credits to the Jinotega twitter for this.

I'm sure I forgot something. I also feel that this blog is like a quick start
guide into stl. Still, I hope a lot of you will find something useful here. C++, as
every other language (programming or natural), is evolving, after all, and we
should keep our eyes on how we can use it efficiently.

###################################################################################
###########

C++ STYLE GUIDE:

Competitive C++ Manifesto: A Style Guide


There are many style guides for C++ out there, but we can't really use them as
competitive programmers. We just want to write our code correctly as fast as
possible! Trying to hack people here on codeforces, I realized there is a need for
a style guide! Our goal is to write correct, fast, clear and consistent code.

Disclaimer
This is not a rulebook. You can integrate parts of it into your coding style. Don't
overthink it, especially during a contest!

I'm going to use this guide for myself and to teach my students. I'm planning to
make some good stuff in the future following these principles! Stay tuned!

Compiler
Make use of C++17. Use -Wall -Wextra -Wshadow flags for compilation, and try to
eliminate all of the warning messages, this will prevent you from having some silly
bugs. There are more debugging flags like -fsanitize=undefined which helps you
eliminate bugs such as array out-of-range access and integer overflow during
runtime. For more information, check out "Read More" section.

Naming
C++ libraries use snake_case for functions and classes, in order to differentiate
the user-defined code from the standard library, we will use CamelCase.

Types use UpperCamelCase: Point, SegTree


Functions and variables use lowerCamelCase: someMethod, someVariable
Macros and constants use all capital letters seperated by _: SOME_MACRO, MAX_N, MOD
Use meaningful names or at least meaningful enough for you.
Example
#define LOCAL
const double PI = 3.14;

struct MyPoint {
int x, y;
bool someProperty;

int someMethod() {
return someProperty ? x : y;
}
};
Note
Using snake_case is fine, but be consistent!

Comments
In competitive programming, you usually don't want to write long comments, but in
case you do want to write some comments, write them using // instead of /* */.
Using // enables you to comment out a chunk of code with /* */ while debugging, and
/* /* ... */ */ is a bug!

Example
/* commenting out a block of code - no problem!

// some comment about the function below...


void someFunction() {
// do something
}

*/
Spacing
Control flow statements are if / else / for / while / ...

Indent using 2 or 4 spaces uniformly. Avoid using tabs since it might make the code
stretched out in different websites (e.g. Codeforces) and also in print (e.g.
ICPC). Set your editor to emit spaces when you hit the tab key.
Braces always open on the same line but close on a new line.
Preferably always use braces for control flow statement blocks even if it's
currently only one line.
else should start on the same line after closing brace of if block.
Keep lines a reasonable length, some say 80 columns!
There should be exactly one blank line between methods. This helps you to organize
your code better.
There should be no blank line after an opening brace or before a closing brace.
Binary operations should be spaced from both sides.
Unary operations should only be spaced from the left side.
Brackets <> [] {} are a part of their identifier like a[5], vector<int> or pair{1,
2}.
Parentheses should only be spaced from outside like (-a[3] + b) * (c + d).
Semicolons and commas should only be spaced from the right side.
Question marks and colons should be spaced from both sides (unlike English!). The
only exceptions are labels like public: or switch cases case 10:.
There should not be any extra spaces at the end of each line.
Add a single newline character at the end of the file.
There should be exactly one space after control flow statements like if (flag).
In contrast to control flow statements, function calls should not be spaced like
func(arg).
Preprocess statements should be written like #define SOME_MACRO and #include
<iostream>.
Templates should be written like template <typename T> and a new line.
Scope resolution operator :: is a part of the identifier and should not be spaced.
Pointer and reference are a part of the type, space accordingly! Like int* ptr and
const string& str. To avoid bugs, declare only one pointer per line.
. and -> operator should not be spaced. When -> is used to show return type (like
in lambda expressions) it should be spaced from both sides.
Lambda expressions should be written like [](int x) -> int { return x + 1; }. The
return type can be omitted most of the times. Feel free to expand the body exactly
like a function if it has more than 1 line of code.
When overloading operators, treat them like functions, no spacing in the name like
bool operator!();
Ellipsis ... should only be spaced from the left side.
Example
#include <bits/stdc++.h>

using namespace std;

const int DIFF = 10;

template <typename T>


struct Point {
T x, y;

Point(T _x, T _y) : x(_x), y(_y) {}

friend ostream& operator<<(ostream& os, const Point& p) {


return os << "(" << p.x << ", " << p.y << ")";
}
};

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
vector<Point<int>> v;
for (int i = 0; i < 5; ++i) {
v.push_back({i, i + DIFF});
}
for (auto p : v) {
if (p.x + DIFF == p.y) {
cout << p << '\n';
} else {
cout << "huh!?\n"; // will never get printed!
}
}
}
Output
(0, 10)
(1, 11)
(2, 12)
(3, 13)
(4, 14)
Competitive Coding Recommendations
Use #include <bits/stdc++.h> instead of many includes.
Use using namespace std; instead of typing std:: every time.
Use using instead of typedef, for example using ll = long long;. Rationale: It's
more consistent with the style of modern C++.
Use struct instead of class. Rationale: It defaults to public, and you don't need
encapsulation in competitive programming!
Don't use too many macros but don't be afraid of using macros! Rationale: It's not
easy to debug and read a code full of ugly macros. but we're hackers after all!
Use const for defining a constant instead of #define. Rationale: consts have a
type, and they are evaluated at compile time.
To avoid bugs, you can use curly braces for each case of switch statement.
Use auto to increase readability and decrease code size.
Use braced initializer lists.
Use emplace and emplace_back for containers when dealing with pairs and tuples.
Rationale: (elem1, elem2, ...) instead of ({elem1, elem2, ...}).
Use lambda functions! They're especially useful when passing functions as arguments
like in sort. Don't repeat yourself, use lambda functions in your code instead of
copy/pasting.
Use nullptr instead of NULL or 0.
Boolean values are true and false!
Use ios::sync_with_stdio(false); and cin.tie(nullptr); for a faster I/O using
cin/cout.
Use builtin functions starting with __builtin.
GCD and LCM are available in C++17 under gcd and lcm.
Use C++11 for-each style for loops for (auto& elem : vec).
Use C++17 binding style like for (auto& [key, val] : dic) and auto [x, y] =
myPoint;
Use C++17 template argument deduction pair p{1, 2.5}; instead of pair<int, double>
p{1, 2.5};.

If you have a lot of nested loops and conditions, refactor! You probably should be
using functions.
Never use goto! But be brave enough to use goto when you want to break from several
nested loops (in case you just can't refactor it)!
Some websites like codeforces use the flag -DONLINE_JUDGE to compile your code,
this means that you can remove your cerrs or your debug functions automatically or
redirect input/output to file instead of stdin/stdout, etc.
#ifdef ONLINE_JUDGE
#define cerr if (false) cerr
#endif
// Alternatively this can be done using a local -DLOCAL flag
// when compiling on your machine, and using #ifndef LOCAL instead.
Prefer using normal operators like !, &&, ||, ^, ... instead of their alternative
representations not, and, or, xor, .... Rationale: We're not coding in python!
Break down your code into different smaller functions. Your code will be cleaner
and easier to debug.
Don't try to be too clever!
Don't reinvent the wheel! — Make use of standard library!
Use common sense and be consistent!

######################################################################

0) DETECT CYCLE IN DIRECTED GRAPH C++


#include <bits/stdc++.h>
using namespace std;

enum Color {WHITE, GRAY, BLACK};

// Graph class represents a directed graph using


// adjacency list representation
class Graph
{
int V; // No. of vertices
list<int>* adj; // adjacency lists
// DFS traversal of the vertices reachable from v
bool DFSUtil(int v, int color[]);
public:
Graph(int V); // Constructor

// function to add an edge to graph


void addEdge(int v, int w);

bool isCyclic();
};

// Constructor
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}

// Utility function to add an edge


void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v's list.
}

// Recursive function to find if there is back edge


// in DFS subtree tree rooted with 'u'
bool Graph::DFSUtil(int u, int color[])
{
// GRAY : This vertex is being processed (DFS
// for this vertex has started, but not
// ended (or this vertex is in function
// call stack)
color[u] = GRAY;

// Iterate through all adjacent vertices


list<int>::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
int v = *i; // An adjacent of u

// If there is
if (color[v] == GRAY)
return true;

// If v is not processed and there is a back


// edge in subtree rooted with v
if (color[v] == WHITE && DFSUtil(v, color))
return true;
}

// Mark this vertex as processed


color[u] = BLACK;

return false;
}

// Returns true if there is a cycle in graph


bool Graph::isCyclic()
{
// Initialize color of all vertices as WHITE
int *color = new int[V];
for (int i = 0; i < V; i++)
color[i] = WHITE;

// Do a DFS traversal beginning with all


// vertices
for (int i = 0; i < V; i++)
if (color[i] == WHITE)
if (DFSUtil(i, color) == true)
return true;

return false;
}

// Driver code to test above


int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);

if (g.isCyclic())
cout << "Graph contains cycle";
else
cout << "Graph doesn't contain cycle";

return 0;
}

1) C++ BFS

// CPP program to implement BFS as per CLRS


// algorithm.
#include <bits/stdc++.h>
using namespace std;

// Declaring the vectors to store color, distance


// and parent
vector<string> colour;
vector<int> d;
vector<int> p;

/* This function adds an edge to the graph.


It is an undirected graph. So edges are
added for both the nodes. */
void addEdge(vector <int> g[], int u, int v)
{
g[u].push_back(v);
g[v].push_back(u);
}
/* This function does the Breadth First Search*/
void BFSSingleSource(vector <int> g[], int s)
{
// The Queue used for the BFS operation
queue<int> q;

// Pushing the root node inside the queue


q.push(s);

/* Distance of root node is 0 & colour


is gray as it is visited partially now */
d[s] = 0;
colour[s] = "green";

/* Loop to traverse the graph. Traversal


will happen traverse until the queue is
not empty.*/
while (!q.empty())
{
/* Extracting the front element(node)
and poping it out of queue. */
int u = q.front();
q.pop();

cout << u << " ";

/* This loop traverses all the child nodes of u */


for (auto i = g[u].begin(); i != g[u].end(); i++)
{
/* If the colour is white then the said node
is not traversed. */
if (colour[*i] == "white")
{
colour[*i] = "green";
d[*i] = d[u] + 1;
p[*i] = u;

/* Pushing the node inside queue


to traverse its children. */
q.push(*i);
}
}

/* Now the node u is completely traversed


and colour is changed to black. */
colour[u] = "dark_green";
}
}

void BFSFull(vector <int> g[], int n)


{
/* Initially all nodes are not traversed.
Therefore, the colour is white. */
colour.assign(n, "white");
d.assign(n, 0);
p.assign(n, -1);

// Calling BFSSingleSource() for all white


// vertices.
for (int i = 0; i < n; i++)
if (colour[i] == "white")
BFSSingleSource(g, i);
}

// Driver Function
int main()
{
// Graph with 7 nodes and 6 edges.
int n = 7;

// The Graph vector


vector <int> g[n];

addEdge(g, 0, 1);
addEdge(g, 0, 2);
addEdge(g, 1, 3);
addEdge(g, 1, 4);
addEdge(g, 2, 5);
addEdge(g, 2, 6);

BFSFull(g, n);

return 0;
}

2) C++ TOPOLOGICAL SORT:

// A C++ program to print topological sorting of a DAG


#include <iostream>
#include <list>
#include <stack>
using namespace std;

// Class to represent a graph


class Graph {
int V; // No. of vertices'

// Pointer to an array containing adjacency listsList


list<int>* adj;

// A function used by topologicalSort


void topologicalSortUtil(int v, bool visited[], stack<int>& Stack);

public:
Graph(int V); // Constructor

// function to add an edge to graph


void addEdge(int v, int w);

// prints a Topological Sort of the complete graph


void topologicalSort();
};

Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}

// A recursive function used by topologicalSort


void Graph::topologicalSortUtil(int v, bool visited[],
stack<int>& Stack)
{
// Mark the current node as visited.
visited[v] = true;

// Recur for all the vertices adjacent to this vertex


list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
topologicalSortUtil(*i, visited, Stack);

// Push current vertex to stack which stores result


Stack.push(v);
}

// The function to do Topological Sort. It uses recursive


// topologicalSortUtil()
void Graph::topologicalSort()
{
stack<int> Stack;

// Mark all the vertices as not visited


bool* visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;

// Call the recursive helper function to store Topological


// Sort starting from all vertices one by one
for (int i = 0; i < V; i++)
if (visited[i] == false)
topologicalSortUtil(i, visited, Stack);

// Print contents of stack


while (Stack.empty() == false) {
cout << Stack.top() << " ";
Stack.pop();
}
}

// Driver program to test above functions


int main()
{
// Create a graph given in the above diagram
Graph g(6);
g.addEdge(5, 2);
g.addEdge(5, 0);
g.addEdge(4, 0);
g.addEdge(4, 1);
g.addEdge(2, 3);
g.addEdge(3, 1);
cout << "Following is a Topological Sort of the given graph n";
g.topologicalSort();

return 0;
}
3) Find ARTICULATION POINTS aka CUT VERTICES in a graph

The idea is to use DFS (Depth First Search). In DFS, we follow vertices in
tree form called DFS tree. In DFS tree, a vertex u is parent of another
vertex v, if v is discovered by u (obviously v is an adjacent of u in graph).
In DFS tree, a vertex u is articulation point if one of the
following two conditions is true.

1) u is root of DFS tree and it has at least two children.


2) u is not root of DFS tree and it has a child v such that no vertex in
subtree rooted with v has a back edge to one of the ancestors (in DFS tree)
of u.

How to handle second case? The second case is trickier.


We maintain an array disc[] to store discovery time of vertices.
For every node u, we need to find out the earliest visited vertex
(the vertex with minimum discovery time) that can be reached from
subtree rooted with u. So we maintain an additional array low[]
which is defined as follows.

low[u] = min(disc[u], disc[w])


where w is an ancestor of u and there is a back edge from
some descendant of u to w.

// A C++ program to find articulation points in an undirected graph


#include<iostream>
#include <list>
#define NIL -1
using namespace std;

// A class that represents an undirected graph


class Graph
{
int V; // No. of vertices
list<int> *adj; // A dynamic array of adjacency lists
void APUtil(int v, bool visited[], int disc[], int low[],
int parent[], bool ap[]);
public:
Graph(int V); // Constructor
void addEdge(int v, int w); // function to add an edge to graph
void AP(); // prints articulation points
};

Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}

void Graph::addEdge(int v, int w)


{
adj[v].push_back(w);
adj[w].push_back(v); // Note: the graph is undirected
}
// A recursive function that find articulation points using DFS traversal
// u --> The vertex to be visited next
// visited[] --> keeps tract of visited vertices
// disc[] --> Stores discovery times of visited vertices
// parent[] --> Stores parent vertices in DFS tree
// ap[] --> Store articulation points
void Graph::APUtil(int u, bool visited[], int disc[],
int low[], int parent[], bool ap[])
{
// A static variable is used for simplicity, we can avoid use of static
// variable by passing a pointer.
static int time = 0;

// Count of children in DFS Tree


int children = 0;

// Mark the current node as visited


visited[u] = true;

// Initialize discovery time and low value


disc[u] = low[u] = ++time;

// Go through all vertices aadjacent to this


list<int>::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
int v = *i; // v is current adjacent of u

// If v is not visited yet, then make it a child of u


// in DFS tree and recur for it
if (!visited[v])
{
children++;
parent[v] = u;
APUtil(v, visited, disc, low, parent, ap);

// Check if the subtree rooted with v has a connection to


// one of the ancestors of u
low[u] = min(low[u], low[v]);

// u is an articulation point in following cases

// (1) u is root of DFS tree and has two or more chilren.


if (parent[u] == NIL && children > 1)
ap[u] = true;

// (2) If u is not root and low value of one of its child is


more
// than discovery value of u.
if (parent[u] != NIL && low[v] >= disc[u])
ap[u] = true;
}

// Update low value of u for parent function calls.


else if (v != parent[u])
low[u] = min(low[u], disc[v]);
}
}
// The function to do DFS traversal. It uses recursive function APUtil()
void Graph::AP()
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
int *disc = new int[V];
int *low = new int[V];
int *parent = new int[V];
bool *ap = new bool[V]; // To store articulation points

// Initialize parent and visited, and ap(articulation point) arrays


for (int i = 0; i < V; i++)
{
parent[i] = NIL;
visited[i] = false;
ap[i] = false;
}

// Call the recursive helper function to find articulation points


// in DFS tree rooted with vertex 'i'
for (int i = 0; i < V; i++)
if (visited[i] == false)
APUtil(i, visited, disc, low, parent, ap);

// Now ap[] contains articulation points, print them


for (int i = 0; i < V; i++)
if (ap[i] == true)
cout << i << " ";
}

// Driver program to test above function


int main()
{
// Create graphs given in above diagrams
cout << "\nArticulation points in first graph \n";
Graph g1(5);
g1.addEdge(1, 0);
g1.addEdge(0, 2);
g1.addEdge(2, 1);
g1.addEdge(0, 3);
g1.addEdge(3, 4);
g1.AP();

cout << "\nArticulation points in second graph \n";


Graph g2(4);
g2.addEdge(0, 1);
g2.addEdge(1, 2);
g2.addEdge(2, 3);
g2.AP();

cout << "\nArticulation points in third graph \n";


Graph g3(7);
g3.addEdge(0, 1);
g3.addEdge(1, 2);
g3.addEdge(2, 0);
g3.addEdge(1, 3);
g3.addEdge(1, 4);
g3.addEdge(1, 6);
g3.addEdge(3, 5);
g3.addEdge(4, 5);
g3.AP();

return 0;
}

4) FIND BRIDGES AKA CUT EDGES in a graph:


We do DFS traversal of the given graph. In DFS tree an edge (u, v) (u is
parent of v in DFS tree)
is bridge if there does not exist any other alternative to reach u or an
ancestor of u
from subtree rooted with v. As discussed in the previous post, the value
low[v]
indicates earliest visited vertex reachable from subtree rooted with v.
The condition for an edge (u, v) to be a bridge is, “low[v] > disc[u]”.

// A C++ program to find bridges in a given undirected graph


#include<iostream>
#include <list>
#define NIL -1
using namespace std;

// A class that represents an undirected graph


class Graph
{
int V; // No. of vertices
list<int> *adj; // A dynamic array of adjacency lists
void bridgeUtil(int v, bool visited[], int disc[], int low[],
int parent[]);
public:
Graph(int V); // Constructor
void addEdge(int v, int w); // to add an edge to graph
void bridge(); // prints all bridges
};

Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}

void Graph::addEdge(int v, int w)


{
adj[v].push_back(w);
adj[w].push_back(v); // Note: the graph is undirected
}

// A recursive function that finds and prints bridges using


// DFS traversal
// u --> The vertex to be visited next
// visited[] --> keeps tract of visited vertices
// disc[] --> Stores discovery times of visited vertices
// parent[] --> Stores parent vertices in DFS tree
void Graph::bridgeUtil(int u, bool visited[], int disc[],
int low[], int parent[])
{
// A static variable is used for simplicity, we can
// avoid use of static variable by passing a pointer.
static int time = 0;

// Mark the current node as visited


visited[u] = true;

// Initialize discovery time and low value


disc[u] = low[u] = ++time;

// Go through all vertices aadjacent to this


list<int>::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
int v = *i; // v is current adjacent of u

// If v is not visited yet, then recur for it


if (!visited[v])
{
parent[v] = u;
bridgeUtil(v, visited, disc, low, parent);

// Check if the subtree rooted with v has a


// connection to one of the ancestors of u
low[u] = min(low[u], low[v]);

// If the lowest vertex reachable from subtree


// under v is below u in DFS tree, then u-v
// is a bridge
if (low[v] > disc[u])
cout << u <<" " << v << endl;
}

// Update low value of u for parent function calls.


else if (v != parent[u])
low[u] = min(low[u], disc[v]);
}
}

// DFS based function to find all bridges. It uses recursive


// function bridgeUtil()
void Graph::bridge()
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
int *disc = new int[V];
int *low = new int[V];
int *parent = new int[V];

// Initialize parent and visited arrays


for (int i = 0; i < V; i++)
{
parent[i] = NIL;
visited[i] = false;
}

// Call the recursive helper function to find Bridges


// in DFS tree rooted with vertex 'i'
for (int i = 0; i < V; i++)
if (visited[i] == false)
bridgeUtil(i, visited, disc, low, parent);
}

// Driver program to test above function


int main()
{
// Create graphs given in above diagrams
cout << "\nBridges in first graph \n";
Graph g1(5);
g1.addEdge(1, 0);
g1.addEdge(0, 2);
g1.addEdge(2, 1);
g1.addEdge(0, 3);
g1.addEdge(3, 4);
g1.bridge();

cout << "\nBridges in second graph \n";


Graph g2(4);
g2.addEdge(0, 1);
g2.addEdge(1, 2);
g2.addEdge(2, 3);
g2.bridge();

cout << "\nBridges in third graph \n";


Graph g3(7);
g3.addEdge(0, 1);
g3.addEdge(1, 2);
g3.addEdge(2, 0);
g3.addEdge(1, 3);
g3.addEdge(1, 4);
g3.addEdge(1, 6);
g3.addEdge(3, 5);
g3.addEdge(4, 5);
g3.bridge();

return 0;
}

4) LINE SWEEPING ALGORITHM:

Given n line segments on the plane. It is required to check whether at


least two of them intersect with each other.
If the answer is yes, then print this pair of intersecting segments; it is
enough to choose any of them among several answers.
This article describes an algorithm with the runtime time O(nlogn), which
is based on the sweep line algorithm.

Algorithm
Let's draw a vertical line x=−∞ mentally and start moving this line to the
right. In the course of its movement,
this line will meet with segments, and at each time a segment intersect
with our line it
intersects in exactly one point (we will assume that there are no vertical
segments).

sweep line and line segment intersection


Thus, for each segment, at some point in time, its point will appear on the
sweep line, then with the movement
of the line, this point will move, and finally, at some point, the segment
will disappear from the line.

We are interested in the relative order of the segments along the vertical.
Namely, we will store a list of
segments crossing the sweep line at a given time,
where the segments will be sorted by their y-coordinate on the sweep line.

relative order of the segments across sweep line


This order is interesting because intersecting segments will have the same
y-coordinate at least at one time:

intersection point having same y-coordinate


We formulate key statements:

To find an intersecting pair, it is sufficient to consider only adjacent


segments at each fixed position of the sweep line.
It is enough to consider the sweep line not in all possible real
positions (−∞…+∞), but only in those positions when new
segments appear or old ones disappear. In other words, it is enough to
limit yourself only
to the positions equal to the abscissas of the end points of the
segments.
When a new line segment appears, it is enough to insert it to the desired
location in the list obtained
for the previous sweep line. We should only check for the intersection
of the added segment
with its immediate neighbors in the list above and below.
If the segment disappears, it is enough to remove it from the current list.
After that,
it is necessary check for the intersection of the upper and lower
neighbors in the list.
Other changes in the sequence of segments in the list, except for
those described, do not exist. No other intersection checks are
required.
To understand the truth of these statements, the following remarks are
sufficient:

Two disjoint segments never change their relative order.

In fact, if one segment was first higher than the other, and then became
lower,
then between these two moments there was an intersection of these two
segments.
Two non-intersecting segments also cannot have the same y-coordinates.
From this it follows that at the moment of the segment appearance we can
find the position for this segment in the queue, and we will
not have to rearrange this segment in the queue any more: its order
relative to other segments in the queue will not change.

Two intersecting segments at the moment of their intersection point will be


neighbors of each other in the queue.
Therefore, for finding pairs of intersecting line segments is sufficient to
check the intersection of all and only those pairs
of segments that sometime during the movement of the sweep line at
least once were neighbors to each other.

It is easy to notice that it is enough only to check the added segment with
its upper and lower neighbors, as well as
when removing the segment — its upper and lower neighbors (which after
removal will become neighbors of each other).
It should be noted that at a fixed position of the sweep line, we must
first add all the segments that start at
this x-coordinate, and only then remove all the segments that end here.
Thus, we do not miss the intersection of segments on the vertex: i.e. such
cases when two segments have a common vertex.
Note that vertical segments do not actually affect the correctness of the
algorithm.
These segments are distinguished by the fact that they appear and disappear
at the same time. However, due to the
previous comment, we know that all segments will be added to the queue
first, and only then they will be deleted.
Therefore, if the vertical segment intersects with some other segment
opened at that moment
(including the vertical one), it will be detected.

In what place of the queue to place vertical segments? After all, a


vertical segment does not have one
specific y-coordinate, it extends for an entire segment along the y-
coordinate. However,
it is easy to understand that any coordinate from this segment can be
taken as a y-coordinate.
Thus, the entire algorithm will perform no more than 2n tests on the
intersection of a pair of segments, and
will perform O(n) operations with a queue of segments (O(1) operations
at the time of appearance and disappearance of each segment).

The final asymptotic behavior of the algorithm is thus O(nlogn).

Implementation:

const double EPS = 1E-9;

struct pt {
double x, y;
};

struct seg {
pt p, q;
int id;

double get_y(double x) const {


if (abs(p.x - q.x) < EPS)
return p.y;
return p.y + (q.y - p.y) * (x - p.x) / (q.x - p.x);
}
};

bool intersect1d(double l1, double r1, double l2, double r2) {


if (l1 > r1)
swap(l1, r1);
if (l2 > r2)
swap(l2, r2);
return max(l1, l2) <= min(r1, r2) + EPS;
}

int vec(const pt& a, const pt& b, const pt& c) {


double s = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
return abs(s) < EPS ? 0 : s > 0 ? +1 : -1;
}

bool intersect(const seg& a, const seg& b)


{
return intersect1d(a.p.x, a.q.x, b.p.x, b.q.x) &&
intersect1d(a.p.y, a.q.y, b.p.y, b.q.y) &&
vec(a.p, a.q, b.p) * vec(a.p, a.q, b.q) <= 0 &&
vec(b.p, b.q, a.p) * vec(b.p, b.q, a.q) <= 0;
}

bool operator<(const seg& a, const seg& b)


{
double x = max(min(a.p.x, a.q.x), min(b.p.x, b.q.x));
return a.get_y(x) < b.get_y(x) - EPS;
}

struct event {
double x;
int tp, id;

event() {}
event(double x, int tp, int id) : x(x), tp(tp), id(id) {}

bool operator<(const event& e) const {


if (abs(x - e.x) > EPS)
return x < e.x;
return tp > e.tp;
}
};

set<seg> s;
vector<set<seg>::iterator> where;

set<seg>::iterator prev(set<seg>::iterator it) {


return it == s.begin() ? s.end() : --it;
}

set<seg>::iterator next(set<seg>::iterator it) {


return ++it;
}

pair<int, int> solve(const vector<seg>& a) {


int n = (int)a.size();
vector<event> e;
for (int i = 0; i < n; ++i) {
e.push_back(event(min(a[i].p.x, a[i].q.x), +1, i));
e.push_back(event(max(a[i].p.x, a[i].q.x), -1, i));
}
sort(e.begin(), e.end());

s.clear();
where.resize(a.size());
for (size_t i = 0; i < e.size(); ++i) {
int id = e[i].id;
if (e[i].tp == +1) {
set<seg>::iterator nxt = s.lower_bound(a[id]), prv = prev(nxt);
if (nxt != s.end() && intersect(*nxt, a[id]))
return make_pair(nxt->id, id);
if (prv != s.end() && intersect(*prv, a[id]))
return make_pair(prv->id, id);
where[id] = s.insert(nxt, a[id]);
} else {
set<seg>::iterator nxt = next(where[id]), prv =
prev(where[id]);
if (nxt != s.end() && prv != s.end() && intersect(*nxt, *prv))
return make_pair(prv->id, nxt->id);
s.erase(where[id]);
}
}

return make_pair(-1, -1);


}

The main function here is solve(), which returns the number of found
intersecting segments, or (−1,−1), if there are no intersections.
Checking for the intersection of two segments is carried out by the
intersect () function,
using an algorithm based on the oriented area of the triangle.
The queue of segments is the global variable s, a set<event>. Iterators
that specify the
position of each segment in the queue (for convenient removal of segments
from the queue)
are stored in the global array where.
Two auxiliary functions prev() and next() are also introduced, which return
iterators to the previous and next elements (or end(), if one does not
exist).
The constant EPS denotes the error of comparing two real numbers
(it is mainly used when checking two segments for intersection).

You might also like