mirror of
https://hub.njuu.cf/TheAlgorithms/C-Plus-Plus.git
synced 2023-10-11 13:05:55 +08:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
990e578abe
179
geometry/jarvis_algorithm.cpp
Normal file
179
geometry/jarvis_algorithm.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of [Jarvis’s](https://en.wikipedia.org/wiki/Gift_wrapping_algorithm) algorithm.
|
||||
*
|
||||
* @details
|
||||
* Given a set of points in the plane. the convex hull of the set
|
||||
* is the smallest convex polygon that contains all the points of it.
|
||||
*
|
||||
* ### Algorithm
|
||||
* The idea of Jarvis’s Algorithm is simple, we start from the leftmost point
|
||||
* (or point with minimum x coordinate value) and we
|
||||
* keep wrapping points in counterclockwise direction.
|
||||
*
|
||||
* The idea is to use orientation() here. Next point is selected as the
|
||||
* point that beats all other points at counterclockwise orientation, i.e.,
|
||||
* next point is q if for any other point r,
|
||||
* we have “orientation(p, q, r) = counterclockwise”.
|
||||
*
|
||||
* For Example,
|
||||
* If points = {{0, 3}, {2, 2}, {1, 1}, {2, 1},
|
||||
{3, 0}, {0, 0}, {3, 3}};
|
||||
*
|
||||
* then the convex hull is
|
||||
* (0, 3), (0, 0), (3, 0), (3, 3)
|
||||
*
|
||||
* @author [Rishabh Agarwal](https://github.com/rishabh-997)
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* @namespace geometry
|
||||
* @brief Geometry algorithms
|
||||
*/
|
||||
namespace geometry {
|
||||
/**
|
||||
* @namespace jarvis
|
||||
* @brief Functions for [Jarvis’s](https://en.wikipedia.org/wiki/Gift_wrapping_algorithm) algorithm
|
||||
*/
|
||||
namespace jarvis {
|
||||
/**
|
||||
* Structure defining the x and y co-ordinates of the given
|
||||
* point in space
|
||||
*/
|
||||
struct Point {
|
||||
int x, y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class which can be called from main and is globally available
|
||||
* throughout the code
|
||||
*/
|
||||
class Convexhull {
|
||||
std::vector<Point> points;
|
||||
int size;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor of given class
|
||||
*
|
||||
* @param pointList list of all points in the space
|
||||
* @param n number of points in space
|
||||
*/
|
||||
explicit Convexhull(const std::vector<Point> &pointList) {
|
||||
points = pointList;
|
||||
size = points.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates convex hull of a set of n points.
|
||||
* There must be 3 points at least for the convex hull to exist
|
||||
*
|
||||
* @returns an vector array containing points in space
|
||||
* which enclose all given points thus forming a hull
|
||||
*/
|
||||
std::vector<Point> getConvexHull() const {
|
||||
// Initialize Result
|
||||
std::vector<Point> hull;
|
||||
|
||||
// Find the leftmost point
|
||||
int leftmost_point = 0;
|
||||
for (int i = 1; i < size; i++) {
|
||||
if (points[i].x < points[leftmost_point].x) {
|
||||
leftmost_point = i;
|
||||
}
|
||||
}
|
||||
// Start from leftmost point, keep moving counterclockwise
|
||||
// until reach the start point again. This loop runs O(h)
|
||||
// times where h is number of points in result or output.
|
||||
int p = leftmost_point, q = 0;
|
||||
do {
|
||||
// Add current point to result
|
||||
hull.push_back(points[p]);
|
||||
|
||||
// Search for a point 'q' such that orientation(p, x, q)
|
||||
// is counterclockwise for all points 'x'. The idea
|
||||
// is to keep track of last visited most counter clock-
|
||||
// wise point in q. If any point 'i' is more counter clock-
|
||||
// wise than q, then update q.
|
||||
q = (p + 1) % size;
|
||||
for (int i = 0; i < size; i++) {
|
||||
// If i is more counterclockwise than current q, then
|
||||
// update q
|
||||
if (orientation(points[p], points[i], points[q]) == 2) {
|
||||
q = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Now q is the most counterclockwise with respect to p
|
||||
// Set p as q for next iteration, so that q is added to
|
||||
// result 'hull'
|
||||
p = q;
|
||||
|
||||
} while (p != leftmost_point); // While we don't come to first point
|
||||
|
||||
return hull;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns the geometric orientation for the three points
|
||||
* in a space, ie, whether they are linear ir clockwise or
|
||||
* anti-clockwise
|
||||
* @param p first point selected
|
||||
* @param q adjacent point for q
|
||||
* @param r adjacent point for q
|
||||
*
|
||||
* @returns 0 -> Linear
|
||||
* @returns 1 -> Clock Wise
|
||||
* @returns 2 -> Anti Clock Wise
|
||||
*/
|
||||
static int orientation(const Point &p, const Point &q, const Point &r) {
|
||||
int val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
|
||||
|
||||
if (val == 0) {
|
||||
return 0;
|
||||
}
|
||||
return (val > 0) ? 1 : 2;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace jarvis
|
||||
} // namespace geometry
|
||||
|
||||
/**
|
||||
* Test function
|
||||
* @returns void
|
||||
*/
|
||||
static void test() {
|
||||
std::vector<geometry::jarvis::Point> points = {{0, 3},
|
||||
{2, 2},
|
||||
{1, 1},
|
||||
{2, 1},
|
||||
{3, 0},
|
||||
{0, 0},
|
||||
{3, 3}
|
||||
};
|
||||
geometry::jarvis::Convexhull hull(points);
|
||||
std::vector<geometry::jarvis::Point> actualPoint;
|
||||
actualPoint = hull.getConvexHull();
|
||||
|
||||
std::vector<geometry::jarvis::Point> expectedPoint = {{0, 3},
|
||||
{0, 0},
|
||||
{3, 0},
|
||||
{3, 3}};
|
||||
for (int i = 0; i < expectedPoint.size(); i++) {
|
||||
assert(actualPoint[i].x == expectedPoint[i].x);
|
||||
assert(actualPoint[i].y == expectedPoint[i].y);
|
||||
}
|
||||
std::cout << "Test implementations passed!\n";
|
||||
}
|
||||
|
||||
/** Driver Code */
|
||||
int main() {
|
||||
test();
|
||||
return 0;
|
||||
}
|
@ -4,77 +4,84 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* Iterative function/method to print graph:
|
||||
* @param a[] : array of vectors (2D)
|
||||
* @param V : vertices
|
||||
* @param a adjacency list representation of the graph
|
||||
* @param V number of vertices
|
||||
* @return void
|
||||
**/
|
||||
void print(vector<int> a[], int V) {
|
||||
void print(const std::vector< std::vector<int> > &a, int V) {
|
||||
for (int i = 0; i < V; i++) {
|
||||
if (!a[i].empty())
|
||||
cout << "i=" << i << "-->";
|
||||
for (int j = 0; j < a[i].size(); j++) cout << a[i][j] << " ";
|
||||
if (!a[i].empty())
|
||||
cout << endl;
|
||||
if (!a[i].empty()) {
|
||||
std::cout << "i=" << i << "-->";
|
||||
}
|
||||
for (int j : a[i]) {
|
||||
std::cout << j << " ";
|
||||
}
|
||||
if (!a[i].empty()) {
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* //Recursive function/method to push vertices into stack passed as parameter:
|
||||
* @param v : vertices
|
||||
* @param &st : stack passed by reference
|
||||
* @param vis[] : array to keep track of visited nodes (boolean type)
|
||||
* @param adj[] : array of vectors to represent graph
|
||||
* @param v vertices
|
||||
* @param st stack passed by reference
|
||||
* @param vis array to keep track of visited nodes (boolean type)
|
||||
* @param adj adjacency list representation of the graph
|
||||
* @return void
|
||||
**/
|
||||
void push_vertex(int v, stack<int> &st, bool vis[], vector<int> adj[]) {
|
||||
vis[v] = true;
|
||||
void push_vertex(int v, std::stack<int> *st, std::vector<bool> *vis, const std::vector< std::vector<int> > &adj) {
|
||||
(*vis)[v] = true;
|
||||
for (auto i = adj[v].begin(); i != adj[v].end(); i++) {
|
||||
if (vis[*i] == false)
|
||||
if ((*vis)[*i] == false) {
|
||||
push_vertex(*i, st, vis, adj);
|
||||
}
|
||||
}
|
||||
st.push(v);
|
||||
st->push(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* //Recursive function/method to implement depth first traversal(dfs):
|
||||
* @param v : vertices
|
||||
* @param vis[] : array to keep track of visited nodes (boolean type)
|
||||
* @param grev[] : graph with reversed edges
|
||||
* @param v vertices
|
||||
* @param vis array to keep track of visited nodes (boolean type)
|
||||
* @param grev graph with reversed edges
|
||||
* @return void
|
||||
**/
|
||||
void dfs(int v, bool vis[], vector<int> grev[]) {
|
||||
vis[v] = true;
|
||||
void dfs(int v, std::vector<bool> *vis, const std::vector< std::vector<int> > &grev) {
|
||||
(*vis)[v] = true;
|
||||
// cout<<v<<" ";
|
||||
for (auto i = grev[v].begin(); i != grev[v].end(); i++) {
|
||||
if (vis[*i] == false)
|
||||
if ((*vis)[*i] == false) {
|
||||
dfs(*i, vis, grev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// function/method to implement Kosaraju's Algorithm:
|
||||
/**
|
||||
* Info about the method
|
||||
* @param V : vertices in graph
|
||||
* @param adj[] : array of vectors that represent a graph (adjacency list/array)
|
||||
* @param V vertices in graph
|
||||
* @param adj array of vectors that represent a graph (adjacency list/array)
|
||||
* @return int ( 0, 1, 2..and so on, only unsigned values as either there can be
|
||||
no SCCs i.e. none(0) or there will be x no. of SCCs (x>0)) i.e. it returns the
|
||||
count of (number of) strongly connected components (SCCs) in the graph.
|
||||
(variable 'count_scc' within function)
|
||||
**/
|
||||
int kosaraju(int V, vector<int> adj[]) {
|
||||
bool vis[V] = {};
|
||||
stack<int> st;
|
||||
int kosaraju(int V, const std::vector< std::vector<int> > &adj) {
|
||||
std::vector<bool> vis(V, false);
|
||||
std::stack<int> st;
|
||||
for (int v = 0; v < V; v++) {
|
||||
if (vis[v] == false)
|
||||
push_vertex(v, st, vis, adj);
|
||||
if (vis[v] == false) {
|
||||
push_vertex(v, &st, &vis, adj);
|
||||
}
|
||||
}
|
||||
// making new graph (grev) with reverse edges as in adj[]:
|
||||
vector<int> grev[V];
|
||||
std::vector< std::vector<int> > grev(V);
|
||||
for (int i = 0; i < V + 1; i++) {
|
||||
for (auto j = adj[i].begin(); j != adj[i].end(); j++) {
|
||||
grev[*j].push_back(i);
|
||||
@ -89,7 +96,7 @@ int kosaraju(int V, vector<int> adj[]) {
|
||||
int t = st.top();
|
||||
st.pop();
|
||||
if (vis[t] == false) {
|
||||
dfs(t, vis, grev);
|
||||
dfs(t, &vis, grev);
|
||||
count_scc++;
|
||||
}
|
||||
}
|
||||
@ -101,21 +108,21 @@ int kosaraju(int V, vector<int> adj[]) {
|
||||
// All critical/corner cases have been taken care of.
|
||||
// Input your required values: (not hardcoded)
|
||||
int main() {
|
||||
int t;
|
||||
cin >> t;
|
||||
int t = 0;
|
||||
std::cin >> t;
|
||||
while (t--) {
|
||||
int a, b; // a->number of nodes, b->directed edges.
|
||||
cin >> a >> b;
|
||||
int m, n;
|
||||
vector<int> adj[a + 1];
|
||||
int a = 0, b = 0; // a->number of nodes, b->directed edges.
|
||||
std::cin >> a >> b;
|
||||
int m = 0, n = 0;
|
||||
std::vector< std::vector<int> > adj(a + 1);
|
||||
for (int i = 0; i < b; i++) // take total b inputs of 2 vertices each
|
||||
// required to form an edge.
|
||||
{
|
||||
cin >> m >> n; // take input m,n denoting edge from m->n.
|
||||
std::cin >> m >> n; // take input m,n denoting edge from m->n.
|
||||
adj[m].push_back(n);
|
||||
}
|
||||
// pass number of nodes and adjacency array as parameters to function:
|
||||
cout << kosaraju(a, adj) << endl;
|
||||
std::cout << kosaraju(a, adj) << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,73 +1,21 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
//#include <boost/multiprecision/cpp_int.hpp>
|
||||
// using namespace boost::multiprecision;
|
||||
const int mx = 1e6 + 5;
|
||||
const long int inf = 2e9;
|
||||
typedef long long ll;
|
||||
#define rep(i, n) for (i = 0; i < n; i++)
|
||||
#define repp(i, a, b) for (i = a; i <= b; i++)
|
||||
#define pii pair<int, int>
|
||||
#define vpii vector<pii>
|
||||
#define vi vector<int>
|
||||
#define vll vector<ll>
|
||||
#define r(x) scanf("%d", &x)
|
||||
#define rs(s) scanf("%s", s)
|
||||
#define gc getchar_unlocked
|
||||
#define pc putchar_unlocked
|
||||
#define mp make_pair
|
||||
#define pb push_back
|
||||
#define lb lower_bound
|
||||
#define ub upper_bound
|
||||
#define endl "\n"
|
||||
#define fast \
|
||||
ios_base::sync_with_stdio(false); \
|
||||
cin.tie(NULL); \
|
||||
cout.tie(NULL);
|
||||
using namespace std;
|
||||
void in(int &x) {
|
||||
register int c = gc();
|
||||
x = 0;
|
||||
int neg = 0;
|
||||
for (; ((c < 48 || c > 57) && c != '-'); c = gc())
|
||||
;
|
||||
if (c == '-') {
|
||||
neg = 1;
|
||||
c = gc();
|
||||
}
|
||||
for (; c > 47 && c < 58; c = gc()) {
|
||||
x = (x << 1) + (x << 3) + c - 48;
|
||||
}
|
||||
if (neg)
|
||||
x = -x;
|
||||
}
|
||||
void out(int n) {
|
||||
int N = n, rev, count = 0;
|
||||
rev = N;
|
||||
if (N == 0) {
|
||||
pc('0');
|
||||
return;
|
||||
}
|
||||
while ((rev % 10) == 0) {
|
||||
count++;
|
||||
rev /= 10;
|
||||
}
|
||||
rev = 0;
|
||||
while (N != 0) {
|
||||
rev = (rev << 3) + (rev << 1) + N % 10;
|
||||
N /= 10;
|
||||
}
|
||||
while (rev != 0) {
|
||||
pc(rev % 10 + '0');
|
||||
rev /= 10;
|
||||
}
|
||||
while (count--) pc('0');
|
||||
}
|
||||
ll parent[mx], arr[mx], node, edge;
|
||||
vector<pair<ll, pair<ll, ll>>> v;
|
||||
using ll = int64_t;
|
||||
|
||||
std::array<ll, mx> parent;
|
||||
ll node, edge;
|
||||
std::vector<std::pair<ll, std::pair<ll, ll>>> edges;
|
||||
void initial() {
|
||||
int i;
|
||||
rep(i, node + edge) parent[i] = i;
|
||||
for (int i = 0; i < node + edge; ++i) {
|
||||
parent[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
int root(int i) {
|
||||
while (parent[i] != i) {
|
||||
parent[i] = parent[parent[i]];
|
||||
@ -75,41 +23,42 @@ int root(int i) {
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void join(int x, int y) {
|
||||
int root_x = root(x); // Disjoint set union by rank
|
||||
int root_y = root(y);
|
||||
parent[root_x] = root_y;
|
||||
}
|
||||
|
||||
ll kruskal() {
|
||||
ll mincost = 0, i, x, y;
|
||||
rep(i, edge) {
|
||||
x = v[i].second.first;
|
||||
y = v[i].second.second;
|
||||
ll mincost = 0;
|
||||
for (int i = 0; i < edge; ++i) {
|
||||
ll x = edges[i].second.first;
|
||||
ll y = edges[i].second.second;
|
||||
if (root(x) != root(y)) {
|
||||
mincost += v[i].first;
|
||||
mincost += edges[i].first;
|
||||
join(x, y);
|
||||
}
|
||||
}
|
||||
return mincost;
|
||||
}
|
||||
|
||||
int main() {
|
||||
fast;
|
||||
while (1) {
|
||||
int i, j, from, to, cost, totalcost = 0;
|
||||
cin >> node >> edge; // Enter the nodes and edges
|
||||
if (node == 0 && edge == 0)
|
||||
while (true) {
|
||||
int from = 0, to = 0, cost = 0, totalcost = 0;
|
||||
std::cin >> node >> edge; // Enter the nodes and edges
|
||||
if (node == 0 && edge == 0) {
|
||||
break; // Enter 0 0 to break out
|
||||
}
|
||||
initial(); // Initialise the parent array
|
||||
rep(i, edge) {
|
||||
cin >> from >> to >> cost;
|
||||
v.pb(mp(cost, mp(from, to)));
|
||||
for (int i = 0; i < edge; ++i) {
|
||||
std::cin >> from >> to >> cost;
|
||||
edges.emplace_back(make_pair(cost, std::make_pair(from, to)));
|
||||
totalcost += cost;
|
||||
}
|
||||
sort(v.begin(), v.end());
|
||||
// rep(i,v.size())
|
||||
// cout<<v[i].first<<" ";
|
||||
cout << kruskal() << endl;
|
||||
v.clear();
|
||||
sort(edges.begin(), edges.end());
|
||||
std::cout << kruskal() << std::endl;
|
||||
edges.clear();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user