Range-based loop for linked list - c++14

I guess I am missing something in operator ++(). I want to implement Range based loop in following Linked list code. I am not sure what I am missing in it.
struct Node {
Node() {}
Node(int e, Node* n) : elem(e), next(n) { }
int elem = 0;
Node* next = nullptr;
Node& operator ++() {
Node* current = this;
if( current != nullptr ) {
current = current->next;
return *current;
}
}
int& operator *() {
return this->elem;
}
bool operator !=(Node const& rhs) const {
return this->elem != rhs.elem;
}
int* begin() {
return &this->elem;
}
int* end() {
return nullptr;
}
};
void add(Node& n, int x) {
n.next = new Node(x, n.next);
}
int main() {
Node head;
add(head, 1);
add(head, 2);
add(head, 3);
add(head, 4);
add(head, 5);
for (int x : head) {
std::cout << x << " ";
}
std::cout << "2nd " << std::endl;
std::cout << std::endl;
for (int& x : head) {
x = 7;
}
std::cout << "3rd " << std::endl;
for (const int& x : head) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}
I am not sure what to add in ++ operator. I want it in same struct instead of having separate Iterator class.

The Node structure contains a single int element. This int element is totally unrelated to any other nodes int element.
What you do with begin and the increment operator ++ is treat one nodes int element as the first element of an array. That means your code will immediately go out of bounds.
To solve your iteration problem I first suggest that you abstract out the list and the nodes into different structures. Then you can easily make a wrapper structure which contains a pointer to the current node in the list iteration. This wrapper structure then need to overload the ++ operator which will the go to the next node in the list.
Somewhat graphically it could be something like
+------+ +--------+ +--------+ +--------+
| list | --> | node 1 | --> | node 2 | --> | node 3 | --> ...
+------+ +--------+ +--------+ +--------+
^
|
+----------+
| iterator |
+----------+
Then you increment the iterator you get this:
+------+ +--------+ +--------+ +--------+
| list | --> | node 1 | --> | node 2 | --> | node 3 | --> ...
+------+ +--------+ +--------+ +--------+
^
|
+----------+
| iterator |
+----------+
And so on...

Related

Special Perfect Maze Generation Algorithm

I'm trying to create a special perfect maze generator.
Instead of the standard case that has rooms and walls, I'm dealing with a grid of cells filled with blocks, where I can remove blocks from some cells:
to connect two given cells (for example, to connect the top-left cell to the bottom-left cell)
in order to have a maximum blocks removed
each removed block cells must me joinable from each other using one way
I use a DFS algorithm to dig the path maze but I can't find a way to be sure that the two given cells are connected.
The normal case goes from here
+-+-+
| | |
+-+-+
| | |
+-+-+
to here
+-+-+
| | |
+ + +
| |
+-+-+
In my case, I'm trying to connect the top-left cell to the bottom-right cell:
##
##
to here
.#
..
or here
..
#.
but not here (because the bottom-right cell is blocked)
..
.#
and not here (the two cells are not connected)
.#
#.
and not here (the maze is not perfect, the cells are connected by more than one path)
..
..
Here two more 8x8 examples :
Good one (perfect maze, and there is a path from the top-left cell to the bottom-right cell):
..#.....
.#.#.##.
.......#
.#.#.##.
.##...#.
..#.#...
.##.#.#.
...###..
Bad one (perfect maze, but there is no path from the top-left cell to the bottom-right cell):
...#....
.##..#.#
....##..
#.#...##
#..##...
..#..#.#
#...#...
##.###.#
It looks like it's actually quite reasonable to generate mazes meeting your criteria using a two-step process:
Generate a random maze without regards to whether it's possible to get to the bottom-right corner from the top-left corner.
Repeat step (1) until there's a path to the bottom-right corner.
I've coded this up using two strategies, one based on a randomized depth-first search and one based on a randomized breadth-first search. The randomized depth-first search, on grids of size 100 × 100, generates mazes where the bottom-right corner is reachable from the top-left corner 82% of time. With a randomized breadth-first search, the success rate on 100 × 100 grids is around 70%. So this strategy does indeed appear to be viable; you'll need to generate, on average, about 1.2 mazes with DFS and around 1.4 mazes with BFS before you'll find one that works.
The mechanism I used to generate mazes without loops is based on a generalization of the idea from regular BFS and DFS. In both of those algorithms, we pick some location that (1) we haven't yet visited but (2) is adjacent to somewhere we have, then add the new location in with the previous location as its parent. That is, the newly-added location ends up being adjacent to exactly one of the previously-visited cells. I adapted this idea by using this rule:
Do not convert a full cell to an empty cell if it's adjacent to more than one empty cell.
This rule ensures that we never get any cycles (if something is adjacent to two or more empty locations and we empty it out, we create a cycle by getting to the first location, then moving to the newly-emptied square, then moving to the second location).
Here's a sample 30 × 30 maze generated using the DFS approach:
.#.........#...#.#....#.#..##.
.#.#.#.#.#.#.#.....##....#....
..#...#..#.#.##.#.#.####.#.#.#
#..#.##.##.#...#..#......#.#..
.#..#...#..####..#.#.####..##.
...#..##..#.....#..#....##..#.
.##.#.#.#...####..#.###...#.#.
..#.#.#.###.#....#..#.#.#..##.
#.#...#....#..#.###....###....
...#.###.#.#.#...#..##..#..#.#
.#....#..#.#.#.#.#.#..#..#.#..
..####..#..###.#.#...###..#.#.
.#.....#.#.....#.########...#.
#..#.##..#######.....#####.##.
..##...#........####..###..#..
.#..##..####.#.#...##..#..#..#
..#.#.#.#....#.###...#...#..#.
.#....#.#.####....#.##.#.#.#..
.#.#.#..#.#...#.#...#..#.#...#
.#..##.#..#.#..#.##..##..###..
.#.#...##....#....#.#...#...#.
...#.##...##.####..#..##..##..
#.#..#.#.#.......#..#...#..#.#
..#.#.....#.####..#...##..##..
##..###.#..#....#.#.#....#..#.
...#...#..##.#.#...#####...#..
.###.#.#.#...#.#.#..#...#.#..#
.#...#.##..##..###.##.#.#.#.##
.#.###..#.##.#....#...#.##...#
......#.......#.#...#.#....#..
Here's a sample 30 × 30 maze generated using BFS:
.#..#..#...#......#..##.#.....
..#.#.#.#.#..#.##...#....#.#.#
#...#.......###.####..##...#.#
.#.#..#.#.##.#.......#.#.#..#.
.....#..#......#.#.#.#..#..##.
#.#.#.###.#.##..#.#....#.#....
..##.....##..#.##...##.#...#.#
#....#.#...#..##.##...#.#.##..
.#.#..##.##..##...#.#...##...#
....#...#..#....#.#.#.##..##..
#.##..#.##.##.##...#..#..##..#
....#.##.#..#...#.####.#...#..
.#.##......#..##.#.#.....#..#.
#....#.#.#..#........#.#.#.##.
.#.###..#..#.#.##.#.#...####..
.#.#...#.#...#..#..###.#.#...#
....##.#.##.#..#.####.....#.#.
.#.#.......###.#.#.#.##.##....
#..#.#.#.##.#.#........###.#.#
.#..#..#........##.#.####..#..
...#.#.#.#.#.##.#.###..#.##..#
#.#..#.##..#.#.#...#.#.....#..
....#...##.#.....#.....##.#..#
#.#.#.##...#.#.#.#.#.##..#.##.
...#..#..##..#..#...#..#.#....
#.#.#.##...#.##..##...#....#.#
..#..#...##....##...#...#.##..
#...#..#...#.#..#.#.#.#..#...#
..#..##..##..#.#..#..#.##.##..
#.#.#...#...#...#..#........#.
And, for fun, here's the code I used to generate these numbers and these mazes. First, the DFS code:
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <string>
#include <random>
using namespace std;
/* World Dimensions */
const size_t kNumRows = 30;
const size_t kNumCols = 30;
/* Location. */
using Location = pair<size_t, size_t>; // (row, col)
/* Adds the given point to the frontier, assuming it's legal to do so. */
void updateFrontier(const Location& loc, vector<string>& maze, vector<Location>& frontier,
set<Location>& usedFrontier) {
/* Make sure we're in bounds. */
if (loc.first >= maze.size() || loc.second >= maze[0].size()) return;
/* Make sure this is still a wall. */
if (maze[loc.first][loc.second] != '#') return;
/* Make sure we haven't added this before. */
if (usedFrontier.count(loc)) return;
/* All good! Add it in. */
frontier.push_back(loc);
usedFrontier.insert(loc);
}
/* Given a location, adds that location to the maze and expands the frontier. */
void expandAt(const Location& loc, vector<string>& maze, vector<Location>& frontier,
set<Location>& usedFrontier) {
/* Mark the location as in use. */
maze[loc.first][loc.second] = '.';
/* Handle each neighbor. */
updateFrontier(Location(loc.first, loc.second + 1), maze, frontier, usedFrontier);
updateFrontier(Location(loc.first, loc.second - 1), maze, frontier, usedFrontier);
updateFrontier(Location(loc.first + 1, loc.second), maze, frontier, usedFrontier);
updateFrontier(Location(loc.first - 1, loc.second), maze, frontier, usedFrontier);
}
/* Chooses and removes a random element of the frontier. */
Location sampleFrom(vector<Location>& frontier, mt19937& generator) {
uniform_int_distribution<size_t> dist(0, frontier.size() - 1);
/* Pick our spot. */
size_t index = dist(generator);
/* Move it to the end and remove it. */
swap(frontier[index], frontier.back());
auto result = frontier.back();
frontier.pop_back();
return result;
}
/* Returns whether a location is empty. */
bool isEmpty(const Location& loc, const vector<string>& maze) {
return loc.first < maze.size() && loc.second < maze[0].size() && maze[loc.first][loc.second] == '.';
}
/* Counts the number of empty neighbors of a given location. */
size_t neighborsOf(const Location& loc, const vector<string>& maze) {
return !!isEmpty(Location(loc.first - 1, loc.second), maze) +
!!isEmpty(Location(loc.first + 1, loc.second), maze) +
!!isEmpty(Location(loc.first, loc.second - 1), maze) +
!!isEmpty(Location(loc.first, loc.second + 1), maze);
}
/* Returns whether a location is in bounds. */
bool inBounds(const Location& loc, const vector<string>& world) {
return loc.first < world.size() && loc.second < world[0].size();
}
/* Runs a recursive DFS to fill in the maze. */
void dfsFrom(const Location& loc, vector<string>& world, mt19937& generator) {
/* Base cases: out of bounds? Been here before? Adjacent to too many existing cells? */
if (!inBounds(loc, world) || world[loc.first][loc.second] == '.' ||
neighborsOf(loc, world) > 1) return;
/* All next places. */
vector<Location> next = {
{ loc.first - 1, loc.second },
{ loc.first + 1, loc.second },
{ loc.first, loc.second - 1 },
{ loc.first, loc.second + 1 }
};
shuffle(next.begin(), next.end(), generator);
/* Mark us as filled. */
world[loc.first][loc.second] = '.';
/* Explore! */
for (const Location& nextStep: next) {
dfsFrom(nextStep, world, generator);
}
}
/* Generates a random maze. */
vector<string> generateMaze(size_t numRows, size_t numCols, mt19937& generator) {
/* Create the maze. */
vector<string> result(numRows, string(numCols, '#'));
/* Build the maze! */
dfsFrom(Location(0, 0), result, generator);
return result;
}
int main() {
random_device rd;
mt19937 generator(rd());
/* Run some trials. */
size_t numTrials = 0;
size_t numSuccesses = 0;
for (size_t i = 0; i < 10000; i++) {
numTrials++;
auto world = generateMaze(kNumRows, kNumCols, generator);
/* Can we get to the bottom? */
if (world[kNumRows - 1][kNumCols - 1] == '.') {
numSuccesses++;
/* Print the first maze that works. */
if (numSuccesses == 1) {
for (const auto& row: world) {
cout << row << endl;
}
cout << endl;
}
}
}
cout << "Trials: " << numTrials << endl;
cout << "Successes: " << numSuccesses << endl;
cout << "Percent: " << (100.0 * numSuccesses) / numTrials << "%" << endl;
cout << endl;
return 0;
}
Next, the BFS code:
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <string>
#include <random>
using namespace std;
/* World Dimensions */
const size_t kNumRows = 30;
const size_t kNumCols = 30;
/* Location. */
using Location = pair<size_t, size_t>; // (row, col)
/* Adds the given point to the frontier, assuming it's legal to do so. */
void updateFrontier(const Location& loc, vector<string>& maze, vector<Location>& frontier,
set<Location>& usedFrontier) {
/* Make sure we're in bounds. */
if (loc.first >= maze.size() || loc.second >= maze[0].size()) return;
/* Make sure this is still a wall. */
if (maze[loc.first][loc.second] != '#') return;
/* Make sure we haven't added this before. */
if (usedFrontier.count(loc)) return;
/* All good! Add it in. */
frontier.push_back(loc);
usedFrontier.insert(loc);
}
/* Given a location, adds that location to the maze and expands the frontier. */
void expandAt(const Location& loc, vector<string>& maze, vector<Location>& frontier,
set<Location>& usedFrontier) {
/* Mark the location as in use. */
maze[loc.first][loc.second] = '.';
/* Handle each neighbor. */
updateFrontier(Location(loc.first, loc.second + 1), maze, frontier, usedFrontier);
updateFrontier(Location(loc.first, loc.second - 1), maze, frontier, usedFrontier);
updateFrontier(Location(loc.first + 1, loc.second), maze, frontier, usedFrontier);
updateFrontier(Location(loc.first - 1, loc.second), maze, frontier, usedFrontier);
}
/* Chooses and removes a random element of the frontier. */
Location sampleFrom(vector<Location>& frontier, mt19937& generator) {
uniform_int_distribution<size_t> dist(0, frontier.size() - 1);
/* Pick our spot. */
size_t index = dist(generator);
/* Move it to the end and remove it. */
swap(frontier[index], frontier.back());
auto result = frontier.back();
frontier.pop_back();
return result;
}
/* Returns whether a location is empty. */
bool isEmpty(const Location& loc, const vector<string>& maze) {
return loc.first < maze.size() && loc.second < maze[0].size() && maze[loc.first][loc.second] == '.';
}
/* Counts the number of empty neighbors of a given location. */
size_t neighborsOf(const Location& loc, const vector<string>& maze) {
return !!isEmpty(Location(loc.first - 1, loc.second), maze) +
!!isEmpty(Location(loc.first + 1, loc.second), maze) +
!!isEmpty(Location(loc.first, loc.second - 1), maze) +
!!isEmpty(Location(loc.first, loc.second + 1), maze);
}
/* Generates a random maze. */
vector<string> generateMaze(size_t numRows, size_t numCols, mt19937& generator) {
/* Create the maze. */
vector<string> result(numRows, string(numCols, '#'));
/* Worklist of free locations. */
vector<Location> frontier;
/* Set of used frontier sites. */
set<Location> usedFrontier;
/* Seed the starting location. */
expandAt(Location(0, 0), result, frontier, usedFrontier);
/* Loop until there's nothing left to expand. */
while (!frontier.empty()) {
/* Select a random frontier location to expand at. */
Location next = sampleFrom(frontier, generator);
/* If this spot has exactly one used neighbor, add it. */
if (neighborsOf(next, result) == 1) {
expandAt(next, result, frontier, usedFrontier);
}
}
return result;
}
int main() {
random_device rd;
mt19937 generator(rd());
/* Run some trials. */
size_t numTrials = 0;
size_t numSuccesses = 0;
for (size_t i = 0; i < 10000; i++) {
numTrials++;
auto world = generateMaze(kNumRows, kNumCols, generator);
/* Can we get to the bottom? */
if (world[kNumRows - 1][kNumCols - 1] == '.') {
numSuccesses++;
/* Print the first maze that works. */
if (numSuccesses == 1) {
for (const auto& row: world) {
cout << row << endl;
}
cout << endl;
}
}
}
cout << "Trials: " << numTrials << endl;
cout << "Successes: " << numSuccesses << endl;
cout << "Percent: " << (100.0 * numSuccesses) / numTrials << "%" << endl;
cout << endl;
return 0;
}
Hope this helps!
Below I describe one easy way to build a perfect maze.
The idea is that you have three types of cells: closed cells, open cells, and frontier cells.
A closed cell is a cell that is still blocked: there is no path from the starting cell to that cell.
If there is a path from the starting cell to a cell, then that cell is open.
A frontier cell is a closed cell that is adjacent to an open cell.
This figure shows open, closed, and frontier cells.
+--+--+--+--+--+--+--+--+--+--+
|** **|FF| | | | | | | |
+--+ +--+--+--+--+--+--+--+--+
|FF|**|FF| | | | | | | |
+--+ +--+--+--+--+--+--+--+--+
|** **|FF| | | | | | | |
+ +--+--+--+--+--+--+--+--+--+
|**|FF|FF|FF| | | | | | |
+ +--+--+--+--+--+--+--+--+--+
|** ** ** **|FF| | | | | |
+--+--+--+ +--+--+--+--+--+--+
|FF|FF|FF|**|FF| | | | | |
+--+--+--+--+--+--+--+--+--+--+
| | |FF|FF| | | | | | |
+--+--+--+--+--+--+--+--+--+--+
| | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+
| | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+
| | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+
Cells with '**' in them are open. Cells with 'FF' in them are frontier cells. Blank cells are closed cells.
The idea is that you start with every cell in your grid as closed.
Then, create an initially empty list of cells. That is your frontier.
Open the starting cell and one of the adjacent cells, and add all cells adjacent to those two to the frontier. So if the upper left is the starting cell, then the first two rows are.
+--+--+--+--+--+--+--+--+--+--+
|** **| | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+
| | | | | | | | | | |
And your frontier array contains {[0,2],[1,0],[1,1]}.
Now, perform the following loop until the frontier array is empty:
Randomly select a cell from the frontier array.
Swap that cell with the last cell in the frontier array.
Remove the last cell from the frontier array.
Open that selected frontier cell into an adjacent open cell.
Add any closed cells that are adjacent to the newly-opened cell to the frontier array.
That is guaranteed to create a maze that has a single path from start to finish.
If you don't want to open all of the cells in the graph, then modify the program to stop when the finish cell is selected from the frontier and opened.
Time complexity is O(height * width). As I recall, the maximum size that the frontier array will reach is (2*height*width)/3. In practice, I've never seen it get quite that large.

Initializing a doubly linked list from array parameters

C++ noob reporting in. I'm trying to write a function that will create and initialize a doubly linked list using values that are stored in two different arrays. Here's how my linked list class is set up:
class node {
public:
node *prev;
node *next;
int key;
char type;
};
and here's how my dList class (containing various functions to alter my linked list) is set up:
class dList {
private:
node *head; // dummy head
node *tail; // dummy tail
public:
dList() { // default constructor, creates empty list
head = tail = NULL;
}
~dList() { // deconstructor
node *ptr = head;
while (head != NULL) {
head = head->next;
delete ptr;
}
tail = NULL;
}
dList(int arrayNums[], char arrayChars[], int size); // parametrized constructor, initialize list w/ contents of arrays
void addFront(int k, char t); // creates new node at front of list
void addBack(int k, char t); // creates new node at back of list
node *search(int k); // searches list for occurence of int parameter and returns pointer to node containing key
void find(char t); // outputs all keys that have type equal to character parameter, front to back
void moveFront(node* ptr); // moves node pointed to by parameter to front of list
void moveBack(node* ptr); // moves node pointed to by parameter to back of list
void out(int num, char = 'f'); // outputs first int elements of list, starting at front or back depending on char parameter
void sort(); // peforms a quick or mergesort on items; list should be in increasing order based on integer key
};
I need help implementing my parametrized constructor. Could someone tell me if the function I have now is written correctly? I think it is, but when I run my program, it runs forever--a clear problem. Here's my function as-is:
dList::dList(int arrayNums[], char arrayChars[], int size) {
node *newNode = NULL;
for (int i = 0; i < size; i++) {
if (head == NULL) {
newNode = new node;
newNode->key = arrayNums[i];
newNode->type = arrayChars[i];
newNode->prev = NULL;
newNode->next = NULL;
head = newNode;
tail = newNode;
}
else { // needs work!
newNode = new node;
newNode->key = arrayNums[i];
newNode->type = arrayChars[i];
newNode->prev = tail;
tail->next = newNode;
tail = newNode;
}
if (i == (size - 1)) {
tail->next = NULL;
}
}
}
Thank you very much!
EDIT: here is my main.cpp (code I'm using to test my dList.cpp file)
#include <iostream>
using namespace std;
#include "dList.cpp"
#define SMALL 200
#define MAX 100000
#define ROUNDS 100
int main(){
int i, x[MAX];
char ch[MAX];
for(i=0;i<SMALL;i++) {
x[i] = 2 * (SMALL - i);
ch[i] = 'a' + (i % 26);
}
dList A(x,ch,SMALL), B;
A.out(10);
node *tmp = A.search(2*SMALL-8);
A.moveFront(tmp);
A.out(10);
A.moveBack(tmp);
A.out(10);
A.find('b');
A.sort();
A.out(10);
A.out(10,'b');
A.addBack(500,'d');
A.addFront(501,'z');
A.out(10);
A.out(10,'b');
B.addFront(1,'a');
B.addBack(2,'b');
B.out(2);
for(int j=0; j<ROUNDS; j++){
cout << endl << "round " << j << endl;
for(i=0;i<MAX;i++) {x[i] = 2*MAX-i; ch[i] = 'a'+ (i%26);}
dList A(x,ch,MAX);
node *tmp = A.search(2*MAX-8);
A.moveFront(tmp);
A.moveBack(tmp);
A.sort();
A.out(10);
A.out(10,'b');
}
}

Why am I keep getting WA for this solution for UVa 10511

I am trying to solve this problem, I think I have come up with a correct answer, but I am keep getting WA (wrong answer) response from the judge.
http://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=1452
The problem distilled, is, given a 1 - * relationship between party and person, 1 - * relationship between person and club. Find a 1 - 1 relationship between person and club such that for all person related to a club, the number of persons belong to a any party is less than half of the number of club.
For example, let say we have
Person1 belongs to Party1 and Club1, Club2
Person2 belongs to Party2 and Club2, Club3
Person3 Belongs to Party3 and Club3, Club1
There are two assignments possible.
Person1 Club1
Person2 Club2
Person3 Club3
and
Person1 Club2
Person2 Club3
Person3 Club1
My idea is to model this problem as a maximum flow problem as follow:
For simplicity, let say there are two parties, four persons, and three clubs.
0 is the master source
1, 2 are the nodes representing the two parties
3, 4, 5, 6 are the nodes representing the four persons
7, 8, 9 are the nodes representing the three clubs.
10 is the master sink
master source connects to each party with capacity = (3 + 1)/2 - 1 = 1. That represents there can only be at most 1 person of 1 party representing in the council (or otherwise 2 will be equals to or more than half)
for each party person pair, have a link of capacity 1. That represents each person have only 1 party and used one seat in the previously allocated number.
for each person club pair, have a link of capacity 1. That represents each person can represent one club only.
Last but not least, all clubs goes to sink with capacity 1.
If the graph above has a maximum flow equals to the number of clubs - then there exist an assignment.
I can prove the design is correct as follow:
=>
If there exist a maximum flow of the size, each club node must be sending flow of value 1, implies each club node has exactly one person representing it. The representation respect the constraint of party participation as it has at most that many person in a party representing by the party node flow.
<=
If there is a representation, construct the flow as above, so that a flow exist. The flow is maximum because the maximal possible flow is constrainted by edge connecting to the sink.
So something must be wrong either with the arguments above, or with the implementation.
Without further ado, this is my source code:
#include "stdafx.h"
// http://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=1452
// #define LOG
#include "UVa10511.h"
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <queue>
using namespace std;
int UVa10511_assign_person_number(map<string, int>& person_numbers, map<int, string>& person_namings, string person_name);
int UVa10511_assign_party_number(map<string, int>& party_numbers, map<int, string>& party_namings, string party_name);
int UVa10511_assign_club_number(map<string, int>& club_numbers, map<int, string>& club_namings, string club_name);
int UVa10511_Edmonds_Karps(vector<vector<int>>& capacities, vector<vector<int>>& adjacency_list, int src, int dst);
int UVa10511()
{
string line;
int number_of_test_cases;
cin >> number_of_test_cases;
getline(cin, line); // consume the blank link after the number of test cases
getline(cin, line); // consume the blank link before the first test case
for (int test_case = 0; test_case < number_of_test_cases; test_case++)
{
map<string, int> person_numbers;
map<int, string> person_namings;
map<string, int> party_numbers;
map<int, string> party_namings;
map<string, int> club_numbers;
map<int, string> club_namings;
vector<pair<int, int>> party_members;
vector<pair<int, int>> person_clubs;
while(getline(cin, line) && line != "" && line != " ")
{
string person_name;
string party_name;
string club_name;
stringstream sin(line);
sin >> person_name >> party_name;
int person_id = UVa10511_assign_person_number(person_numbers, person_namings, person_name);
int party_id = UVa10511_assign_party_number(party_numbers, party_namings, party_name);
party_members.push_back(pair<int, int>(party_id, person_id));
while(sin >> club_name)
{
int club_id = UVa10511_assign_club_number(club_numbers, club_namings, club_name);
person_clubs.push_back(pair<int, int>(person_id, club_id));
}
}
int number_of_parties = party_numbers.size();
int number_of_persons = person_numbers.size();
int number_of_clubs = club_numbers.size();
int number_of_nodes =
/* master source */ 1 +
/* parties */ number_of_parties +
/* person */ number_of_persons +
/* clubs */ number_of_clubs +
/* master sink */ 1;
vector<vector<int>> capacities;
vector<vector<int>> adjacency_list;
capacities.resize(number_of_nodes);
adjacency_list.resize(number_of_nodes);
for (int src = 0; src < number_of_nodes; src++)
{
capacities[src].resize(number_of_nodes);
for (int dst = 0; dst < number_of_nodes; dst++)
{
capacities[src][dst] = 0;
}
}
int max_party_participants = (number_of_clubs - 1) / 2; // Floor intended, not equal or more than half
for (int p = 0; p < number_of_parties; p++)
{
int party_node = p + 1;
capacities[0][party_node] = max_party_participants;
adjacency_list[0].push_back(party_node);
adjacency_list[party_node].push_back(0);
}
int person_node_start = 1 + number_of_parties;
for (vector<pair<int, int>>::iterator pmi = party_members.begin(); pmi != party_members.end(); pmi++)
{
int party_id = pmi->first;
int person_id = pmi->second;
int party_node = party_id + 1;
int person_node = person_node_start + person_id;
capacities[party_node][person_node] = 1;
adjacency_list[party_node].push_back(person_node);
adjacency_list[person_node].push_back(party_node);
}
int club_node_start = 1 + number_of_parties + number_of_persons;
for (vector<pair<int, int>>::iterator pci = person_clubs.begin(); pci != person_clubs.end(); pci++)
{
int person_id = pci->first;
int club_id = pci->second;
int person_node = person_node_start + person_id;
int club_node = club_node_start + club_id;
capacities[person_node][club_node] = 1;
adjacency_list[person_node].push_back(club_node);
adjacency_list[club_node].push_back(person_node);
}
for (int c = 0; c < number_of_clubs; c++)
{
int club_node = club_node_start + c;
capacities[club_node][number_of_nodes - 1] = 1;
adjacency_list[club_node].push_back(number_of_nodes - 1);
adjacency_list[number_of_nodes - 1].push_back(club_node);
}
#ifdef LOG
cout << "digraph {" << endl;
for (int src = 0; src < number_of_nodes; src++)
{
for (vector<int>::iterator di = adjacency_list[src].begin(); di != adjacency_list[src].end(); di++)
{
int dst = *di;
cout << src << "->" << dst << " [label=\"" << capacities[src][dst] << "\"];" << endl;
}
}
cout << "}" << endl;
#endif
int total_flow = UVa10511_Edmonds_Karps(capacities, adjacency_list, 0, number_of_nodes - 1);
if (test_case > 0)
{
cout << endl;
}
if (total_flow == number_of_clubs)
{
for (vector<pair<int, int>>::iterator pci = person_clubs.begin(); pci != person_clubs.end(); pci++)
{
int person_id = pci->first;
int club_id = pci->second;
int person_node = person_node_start + person_id;
int club_node = club_node_start + club_id;
if (capacities[person_node][club_node] == 0)
{
cout << person_namings[person_id] << " " << club_namings[club_id] << endl;
}
}
}
else
{
cout << "Impossible." << endl;
}
}
return 0;
}
int UVa10511_assign_party_number(map<string, int>& party_numbers, map<int, string>& party_namings, string party_name)
{
int party_number;
map<string, int>::iterator probe = party_numbers.find(party_name);
if (probe == party_numbers.end())
{
party_number = party_numbers.size();
party_numbers.insert(pair<string, int>(party_name, party_number));
party_namings.insert(pair<int, string>(party_number, party_name));
}
else
{
party_number = probe->second;
}
return party_number;
}
int UVa10511_assign_person_number(map<string, int>& person_numbers, map<int, string>& person_namings, string person_name)
{
int person_number;
map<string, int>::iterator probe = person_numbers.find(person_name);
if (probe == person_numbers.end())
{
person_number = person_numbers.size();
person_numbers.insert(pair<string, int>(person_name, person_number));
person_namings.insert(pair<int, string>(person_number, person_name));
}
else
{
person_number = probe->second;
}
return person_number;
}
int UVa10511_assign_club_number(map<string, int>& club_numbers, map<int, string>& club_namings, string club_name)
{
int club_number;
map<string, int>::iterator probe = club_numbers.find(club_name);
if (probe == club_numbers.end())
{
club_number = club_numbers.size();
club_numbers.insert(pair<string, int>(club_name, club_number));
club_namings.insert(pair<int, string>(club_number, club_name));
}
else
{
club_number = probe->second;
}
return club_number;
}
int UVa10511_Edmonds_Karps(vector<vector<int>>& capacities, vector<vector<int>>& adjacency_list, int src, int dst)
{
int total_flow = 0;
// Step 2: Edmonds Karp's
vector<int> parents; // Allow back-tracking the path found from bfs
int number_of_nodes = capacities.size();
parents.resize(number_of_nodes); // avoid reallocation
while (true)
{
// Step 2.1: Use BFS to find an augmenting flow
queue<int> bfs_queue;
for (int n = 0; n < number_of_nodes; n++)
{
parents[n] = -1; // indicating the node is not enqueued
}
parents[src] = -2; // indicating the node is enqueued but no actual parent because this is the root
bfs_queue.push(src);
while (bfs_queue.size() > 0)
{
int current = bfs_queue.front();
bfs_queue.pop();
for (vector<int>::iterator ni = adjacency_list[current].begin(); ni != adjacency_list[current].end(); ni++)
{
int neighbor = *ni;
if (parents[neighbor] == -1 && capacities[current][neighbor] > 0)
{
parents[neighbor] = current;
bfs_queue.push(neighbor);
if (neighbor == dst)
{
break;
}
}
}
if (parents[dst] != -1)
{
break;
}
}
if (parents[dst] == -1)
{
break;
}
else
{
// We have found an augmenting path, go through the path and find the max flow through this path
int cur = dst;
bool first = true;
int max_flow_through_path = 0;
while (true)
{
int src = parents[cur];
if (src != -2)
{
int dst = cur;
int available = capacities[src][dst];
#ifdef LOG
cout << src << "--" << available << "->" << dst << endl;
#endif
cur = parents[cur];
if (first)
{
max_flow_through_path = available;
first = false;
}
else
{
max_flow_through_path = min(max_flow_through_path, available);
}
}
else
{
break;
}
}
#ifdef LOG
cout << "flowing " << max_flow_through_path << endl << endl;
#endif
total_flow += max_flow_through_path;
// Flow the max flow through the augmenting path
cur = dst;
while (true)
{
int src = parents[cur];
if (src != -2)
{
capacities[src][cur] -= max_flow_through_path;
capacities[cur][src] += max_flow_through_path;
cur = parents[cur];
}
else
{
break;
}
}
}
}
return total_flow;
}
The source code is also posted in
https://github.com/cshung/Competition/blob/master/Competition/UVa10511.cpp
The same Edmonds Karps procedure is used to pass some other UVa problems, so I think it should be fine.
UVa820, UVa10480, UVa10779, UVa11506, UVa563 are all accepted with this Edmonds Karp procedure
(These code can be found in the Git repository as well)
I have even debugging the case where Edmond Karps make a wrong choice to being with a fixed it with an augmenting path for this test case
1
Person1 Party1 Club1 Club2
Person2 Party2 Club3
Person3 Party3 Club1
As my Edmond Karps used BFS in the adjacency list order, The chosen paths are
Master Source -> Party1 -> Person1 -> Club1 -> Master Sink
Master Source -> Party2 -> Person2 -> Club3 -> Master Sink
Master Source -> Party3 -> Person3 -> Club1 -> Person1 -> Club2 -> Master Sink [This used the reverse edge and proved going through reverse edge works]
Now I am really stuck, really don't know what's wrong, any help is appreciated.
Your thinking for this problem is correct, it is a typical problem that use maximum flow algorithm.
I have read your code over and over again, I can't find any mistake. Then I change the way you handle the input, then I got accept from UVA.
Just change the code
// you code
cin >> number_of_test_cases;
getline(cin, line); // consume the blank link before the first test case
getline(cin, line); // consume the blank link before the first test case
//line 43
while(getline(cin, line) && line != "" && line != " ")
// change to
scanf("%d\n", &number_of_test_cases);
//line 43
// while(getline(cin, line) && line.length() > 0)
After change the code, I got accept from uva .
Hope get accept response from you.

Is it possible to have several edge weight property maps for one graph?

How would I create a graph, such that the property map (weight of edges) is different in each property map? Is it possible to create such a property map?
Like an array of property maps?
I have not seen anyone on the Internet using it, could I have an example?
Graph g(10); // graph with 10 nodes
cin>>a>>b>>weight1>>weight2>>weight3>>weight4;
and put each weight in a property map.
You can compose a property map in various ways. The simplest approach would seem something like:
Using C++11 lambdas with function_property_map
Live On Coliru
#include <boost/property_map/function_property_map.hpp>
#include <iostream>
struct weights_t {
float weight1, weight2, weight3, weight4;
};
using namespace boost;
int main() {
std::vector<weights_t> weight_data { // index is vertex id
{ 1,2,3,4 },
{ 5,6,7,8 },
{ 9,10,11,12 },
{ 13,14,15,16 },
};
auto wmap1 = make_function_property_map<unsigned, float>([&weight_data](unsigned vertex_id) { return weight_data.at(vertex_id).weight1; });
auto wmap2 = make_function_property_map<unsigned, float>([&weight_data](unsigned vertex_id) { return weight_data.at(vertex_id).weight2; });
auto wmap3 = make_function_property_map<unsigned, float>([&weight_data](unsigned vertex_id) { return weight_data.at(vertex_id).weight3; });
auto wmap4 = make_function_property_map<unsigned, float>([&weight_data](unsigned vertex_id) { return weight_data.at(vertex_id).weight4; });
for (unsigned vertex = 0; vertex < weight_data.size(); ++vertex)
std::cout << wmap1[vertex] << "\t" << wmap2[vertex] << "\t" << wmap3[vertex] << "\t"<< wmap4[vertex] << "\n";
}
Using C++03 with transform_value_property_map
This is mainly much more verbose:
Live On Coliru
#include <boost/property_map/transform_value_property_map.hpp>
#include <iostream>
struct weights_t {
float weight1, weight2, weight3, weight4;
weights_t(float w1, float w2, float w3, float w4)
: weight1(w1), weight2(w2), weight3(w3), weight4(w4)
{ }
template <int which> struct access {
typedef float result_type;
float operator()(weights_t const& w) const {
BOOST_STATIC_ASSERT(which >= 1 && which <= 4);
switch (which) {
case 1: return w.weight1;
case 2: return w.weight2;
case 3: return w.weight3;
case 4: return w.weight4;
}
}
};
};
using namespace boost;
int main() {
std::vector<weights_t> weight_data; // index is vertex id
weight_data.push_back(weights_t(1,2,3,4));
weight_data.push_back(weights_t(5,6,7,8));
weight_data.push_back(weights_t(9,10,11,12));
weight_data.push_back(weights_t(13,14,15,16));
boost::transform_value_property_map<weights_t::access<1>, weights_t*, float> wmap1 = make_transform_value_property_map(weights_t::access<1>(), &weight_data[0]);
boost::transform_value_property_map<weights_t::access<2>, weights_t*, float> wmap2 = make_transform_value_property_map(weights_t::access<2>(), &weight_data[0]);
boost::transform_value_property_map<weights_t::access<3>, weights_t*, float> wmap3 = make_transform_value_property_map(weights_t::access<3>(), &weight_data[0]);
boost::transform_value_property_map<weights_t::access<4>, weights_t*, float> wmap4 = make_transform_value_property_map(weights_t::access<4>(), &weight_data[0]);
for (unsigned vertex = 0; vertex < weight_data.size(); ++vertex)
std::cout << wmap1[vertex] << "\t" << wmap2[vertex] << "\t" << wmap3[vertex] << "\t"<< wmap4[vertex] << "\n";
}
Output
Both samples output
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16

How to form a Binary Tree from a Preorder and a Children charsequence

The problem is to build a Binary Tree from a Preorder listing and a sequence of the number of children that each node has. For example: "BAC" and "200" could be one input resulting in an inorder listing of "ABC".
My current method is to check the second charsequence (the one with the numbers) for '2', it has two children, '0',it has no children, 'L', it has a left child, and 'R', it has a right child. To do this I use this method:
public static BinaryTree preOrderBuild(CharSequence charElements,
CharSequence childCodes) {
// TODO Auto-generated method stub.
BinaryTree build = new BinaryTree();
char first;
if (childCodes.length() == 0) {
return new BinaryTree();
} else {
first = childCodes.charAt(0);
}
if (first == '2') {
int sum = 1;
for (int i = 1; i < childCodes.length(); i++) {
if (childCodes.charAt(i) == 'R' || childCodes.charAt(i) == 'L')
sum += 0;
else if (childCodes.charAt(i) == '2')
sum += 1;
else if (childCodes.charAt(i) == '0')
sum--;
if (sum == 0) {
BinaryTree Left = preOrderBuild(
charElements.subSequence(1, i + 1),
childCodes.subSequence(1, i + 1));
BinaryTree Right = preOrderBuild(
charElements.subSequence(i + 1,
charElements.length()),
childCodes.subSequence(i + 1, childCodes.length()));
build.merge(charElements.charAt(0), Left, Right);
}
}
} else if (first == 'R' || first == 'r') {
BinaryTree right = preOrderBuild(
charElements.subSequence(1, charElements.length()),
childCodes.subSequence(1, childCodes.length()));
build.merge(charElements.charAt(0), new BinaryTree(), right);
} else if (first == 'L' || first == 'l') {
BinaryTree left = preOrderBuild(
charElements.subSequence(1, charElements.length()),
childCodes.subSequence(1, childCodes.length()));
build.merge(charElements.charAt(0), left, new BinaryTree());
} else {
build.merge(charElements.charAt(0), new BinaryTree(),
new BinaryTree());
}
return build;
}
which basically processes the childCodes sequence to determine where each branch of the tree breaks off. The problem is that for larger trees it only processes the first few items and then collapses. (an example of the larger tree is : "ABCDEFGHIJKLMNOPQRSTU" with child code "220022002200LRR20RLL0")
If you go from right to left, you don't need to do any recursion.
Stack<BinaryTree> stack = new Stack<BinaryTree>();
for (int i = childCodes.length() - 1; i >= 0; i--) {
char code = childCodes.charAt(i);
char name = charElements.charAt(i);
if (code == '0') {
stack.push(new BinaryTree(name, null, null));
}
else if (code == 'L') {
stack.push(new BinaryTree(name, stack.pop(), null));
}
else if (code == 'R') {
stack.push(new BinaryTree(name, null, stack.pop()));
}
else if (code == '2') {
stack.push(new BinaryTree(name, stack.pop(), stack.pop()));
}
}
return stack.pop();
With your data, it produces the following tree:
A
+-B
| +-C
| '-D
'-E
+-F
| +-G
| '-H
'-I
+-J
| +-K
| '-L
'-M
+-N
| +-(null)
| '-O
| +-(null)
| '-P
| +-Q
| '-R
| +-(null)
| '-S
| +-T
| | +-U
| | '-(null)
| '-(null)
'-(null)

Resources