So i have got this function.
UINT32 Encrypt(UINT32 instruction, int increment)
{
UINT32 linstruction = _rotl(instruction, 7);
UINT32 rinstruction = _rotr(instruction, 3);
UINT32 key = (0x1F3D8AF * increment) ^ (rinstruction ^ linstruction);
return (key ^ instruction);
}
I need to make a function that actually decrypts this and gets the instruction from the result using a key so it would be like.
t = encrypt(t, i);
t = decrypt(t, key);
Basically i want it to reverse the whole process of the encrypt so it decrypts it and gets me the instruction.
They are used in this function
int RbxOpEncoder::encode(Instruction op, int i, int key) {
int orig = ConvertInstruction(op);
int t = orig;
switch (GET_OPCODE(op)) {
case OP_JMP:
t = ((Encrypt(t, i) & 0x3FFFFFF) | ((orig >> 26 & MASK1(6, 0)) << 0x1A));
break;
case OP_CALL:
case OP_TAILCALL:
case OP_CLOSURE:
case OP_RETURN:
t = ((Calldecrypt(t, i) & 0x3FFFFFF) | ((orig >> 26 & MASK1(6, 0)) << 0x1A));
break;
}
t = EncryptOpcode(t, key);
return t;
}
You may use:
std::uint32_t decrypt(std::uint32_t instruction, int increment)
{
instruction = instruction ^ (0x1F3D8AF * increment);
for (int i = 0; i != 15; ++i) {
instruction = Encrypt(instruction, 0);
}
return instruction;
}
And then you have
decrypt(Encrypt(value, increment), increment) == value
Demo
Related
I have been working on a program that can connect to a Minecraft Server and exchange packets with it but Minecraft's server packets heavily rely on signed VarInts. On the site documenting how their communication works is explanation of VarInt and even an example implementation of them in Java:
So i followed it and it works for non negative numbers but for negative numbers it's just goes infinitely long. I serched for other means of implementing it but i couldn't find any.
Here is my version it (works as i said only for positive numbers which is not fully what i want)
class VarInt
{
public:
char* data = NULL;
int length = 0;
int Read();
void Write(int value);
~VarInt();
private:
int SEGMENT_BIT_MASK = 0x7F;
int CONTINUE_BIT_MASK = 0x80;
};
int VarInt::Read()
{
int value = 0;
int position = 0;
byte currentByte;
int i = 0;
while (true)
{
currentByte = data[i];
value |= (currentByte & SEGMENT_BIT_MASK) << position;
if ((currentByte & CONTINUE_BIT_MASK) == 0)
break;
i++;
position += 7;
if (position >= 32)
std::cout << "VarInt is too Big" << std::endl;
}
return value;
};
void VarInt::Write(int value)
{
bool state = true;
std::vector<byte> bytes;
while (state)
{
if ((value & ~SEGMENT_BIT_MASK) == 0)
{
bytes.push_back(value);
state = false;
break;
}
bytes.push_back(((value & SEGMENT_BIT_MASK) | CONTINUE_BIT_MASK));
value >>= 7;
}
int bytes_size = bytes.size();
length = bytes_size;
data = (char*)malloc(bytes_size);
int i = 0;
while (i != bytes_size)
{
data[i] = bytes.at(i);
i++;
}
};
VarInt::~VarInt()
{
};
And here are my means of testing it:
#include <iostream>
#include "MDatatypes.h"
int main()
{
ndt::VarInt test;
//Sets value of test to -127
test.Write(-127);
//Sets value of test2 to 255
ndt::VarInt test2;
test2.Write(255);
//Outputing length of each Varint in bytes
std::cout << test.length << '|' << test2.length << std::endl;
//Outputing the values of each Varint
std::cout << test.Read() << '|' << test2.Read() << std::endl;
}
I've been working on a C++ program, I've made the logic but I'm unable to execute it. The question is:
Task: Write a program, using functions only, with the following features.
Program reads paragraph(s) from the file and stores in a string.
Then program counts the occurrence of each word in the paragraph(s) and stores all words with their number of occurrences.
If that word has appeared more than one time in whole string, it should store the word only once along its total occurrences.
The output described in above (in part 3) must be stored in a new file.
Sample input:
is the is and the is and the and is and only that is
Sample output:
is 5
the 3
and 4
only 1
that 1
I'll cut short to Occurrence program that I've written,
My logic is to store token into character array and then compare that array with main character array and do the increment:
void occurances() {
char* string = getInputFromFile();
char separators[] = ",.\n\t ";
char* token;
char* nextToken;
char* temp[100];
token = strtok_s(string, separators, &nextToken);
cout << temp;
int counter = 0;
int i = 0;
while ((token != NULL)) {
temp[i] = token;
i++;
for (int i = 0; i < strlen(string); i++) {
for (int j = 0; j < 100; j++) {
if ((strcmp(token, *temp)) == 0) {
counter++;
}
}
cout << temp << " : " << counter << endl;
}
if (token != NULL) {
token = strtok_s(NULL, separators, &nextToken);
}
}
}
This code is preposterous I know that, But please anyone be kind enough to give me a clue, actually I'm new to C++ . Thank you
If you store token into array this array should grow dynamically because the number of tokens is not known at the beginning. And according to the task description, you cannot use C++ standard containers, so, it is necessary to implement dynamic array manually, for example:
#include <iostream>
std::size_t increase_capacity_value(std::size_t capacity) {
if (capacity == 0) {
return 1;
}
else if (capacity < (SIZE_MAX / 2)) {
return capacity * 2;
}
return SIZE_MAX;
}
bool increase_array_capacity(char**& tokens_array, std::size_t*& tokens_count, std::size_t& capacity) {
const std::size_t new_capacity = increase_capacity_value(capacity);
if (new_capacity <= capacity) {
return false;
}
const std::size_t tokens_array_byte_size = new_capacity * sizeof(char*);
char** const new_tokens_array = static_cast<char**>(std::realloc(tokens_array, tokens_array_byte_size));
if (new_tokens_array == nullptr) {
return false;
}
tokens_array = new_tokens_array;
const std::size_t tokens_count_byte_size = new_capacity * sizeof(std::size_t);
std::size_t* const new_tokens_count = static_cast<std::size_t*>(std::realloc(tokens_count, tokens_count_byte_size));
if (new_tokens_count == nullptr) {
return false;
}
tokens_count = new_tokens_count;
capacity = new_capacity;
return true;
}
bool add_token(char* token, char**& tokens_array, std::size_t*& tokens_count, std::size_t& array_size, std::size_t& array_capacity) {
if (array_size == array_capacity) {
if (!increase_array_capacity(tokens_array, tokens_count, array_capacity)) {
return false;
}
}
tokens_array[array_size] = token;
tokens_count[array_size] = 1;
++array_size;
return true;
}
std::size_t* get_token_count_storage(char* token, char** tokens_array, std::size_t* tokens_count, std::size_t array_size) {
for (std::size_t i = 0; i < array_size; ++i) {
if (std::strcmp(token, tokens_array[i]) == 0) {
return tokens_count + i;
}
}
return nullptr;
}
bool process_token(char* token, char**& tokens_array, std::size_t*& tokens_count, std::size_t& array_size, std::size_t& array_capacity) {
std::size_t* token_count_ptr = get_token_count_storage(token, tokens_array, tokens_count, array_size);
if (token_count_ptr == nullptr) {
if (!add_token(token, tokens_array, tokens_count, array_size, array_capacity)) {
return false;
}
}
else {
++(*token_count_ptr);
}
return true;
}
int main() {
char string[] = "is the is and the is and the and is and only that is";
char separators[] = ",.\n\t ";
std::size_t token_array_capacity = 0;
std::size_t token_array_size = 0;
char** tokens_array = nullptr;
std::size_t* tokens_count = nullptr;
char* current_token = std::strtok(string, separators);
while (current_token != nullptr) {
if (!process_token(current_token, tokens_array, tokens_count, token_array_size, token_array_capacity)) {
break;
}
current_token = std::strtok(nullptr, separators);
}
// print the report only if all tokens were processed
if (current_token == nullptr) {
for (std::size_t i = 0; i < token_array_size; ++i) {
std::cout << tokens_array[i] << " : " << tokens_count[i] << std::endl;
}
}
std::free(tokens_array);
std::free(tokens_count);
}
godbolt.org
okay what if i want to store any token once, in an array and then replace it with new word while deleting duplicates in character array
It is also possible solution. But in general case, it is also necessary to allocate the memory dynamically for the current token. Because the lengths of tokens are also not known at the beginning:
void replace_chars(char* str, const char* chars_to_replace) {
while (str && *str != '\0') {
str = std::strpbrk(str, chars_to_replace);
if (str == nullptr) {
break;
}
const std::size_t number_of_delimiters = std::strspn(str, chars_to_replace);
for (std::size_t i = 0; i < number_of_delimiters; ++i) {
str[i] = '\0';
}
str += number_of_delimiters;
}
}
bool keep_token(char*& token_storage, const char* new_token) {
if (new_token == nullptr) {
return false;
}
const std::size_t current_token_len = token_storage ? std::strlen(token_storage) : 0;
const std::size_t requried_token_len = std::strlen(new_token);
if (token_storage == nullptr || current_token_len < requried_token_len) {
token_storage =
static_cast<char*>(std::realloc(token_storage, (requried_token_len + 1) * sizeof(char)));
if (token_storage == nullptr) {
return false;
}
}
std::strcpy(token_storage, new_token);
return true;
}
std::size_t count_tokens_and_replace(char* str, std::size_t str_len, const char* token) {
std::size_t number_of_tokens = 0;
std::size_t i = 0;
while (i < str_len) {
while (str[i] == '\0') ++i;
if (std::strcmp(str + i, token) == 0) {
replace_chars(str + i, token);
++number_of_tokens;
}
i += std::strlen(str + i);
}
return number_of_tokens;
}
int main() {
char string[] = "is the is and the is and the and is and only that is";
char separators[] = ",.\n\t ";
const std::size_t string_len = std::strlen(string);
replace_chars(string, separators);
std::size_t i = 0;
char* token = nullptr;
while (true) {
while (i < string_len && string[i] == '\0') ++i;
if (i == string_len || !keep_token(token, string + i)) break;
std::cout << token << " : " << count_tokens_and_replace(string + i, string_len - i, token) << std::endl;
}
std::free(token);
}
godbolt.org
But if it is known that the token length cannot be greater than N, it is possible to use the static array of chars to keep the current token. And it will allow to remove dynamic memory allocation from the code.
I need some help, I'm learing data structers and I got a task to write a programm based on array of pointers to structres which can add elements and do other task with array.I have next model of levels:
first level --> net of shops
second level --> shop
third level --> goods
I've written types for this
typedef struct
{
QString date;
QString prod_code;
QString name;
}goods;
typedef struct
{
QString address;
QString number;
void **sublevel;
}shop;
typedef struct
{
QString website;
QString name;
QString owner;
QString address;
void **sublevel;
}net;
Then I've created global variable void **Start which points to array of pointers:
// init list
void ** init_list()
{
void** p = new void*[SIZE_AR];
p = p+2;
((int*)p)[COUNT_POS] = 0;
((int*)p)[SIZE_POS] = SIZE_AR;
return p;
}
void ** Start = init_list();
COUNT_POS - index of elements where I store count of currently used elemnets
SIZE_POS - size of array allocated in dynamic memory
SIZE_AR - default size for array
But I get segmentation fault when I try to add to element to the last level
(for previous two ones works fine):
// expand array if it overfilled
void ExpandArrPtr (void **&ar, int &SizeAr, int Cnt)
{
void **arW;
arW = new void*[SizeAr+DELTA+2];
for (int K = SizeAr-1; K >= 0; K--) {
arW[K+2] = ar[K];
}
SizeAr = SizeAr + DELTA;
ar=ar-2;
delete []ar;
ar=arW+2;
((int*)ar)[COUNT_POS] = Cnt;
((int*)ar)[SIZE_POS] = SizeAr;
}
// binary search
void bin_search(void **start, QString key, int &pos, bool &find, Cmpmethod func)
{
int mid;
int high, low;
find = false;
if((int*)start[COUNT_POS] == 0)
{
pos = 0;
qDebug()<<"zero elem\n";
return;
}
low = 0;
high = ((int*)start)[COUNT_POS] - 1;
do
{
mid = (high + low) / 2;
int result = func(start[mid], key);
if(result == 0)
{
pos = mid;
find = true;
return;
}
else if(result == 1)
{
high = mid - 1;
}
else
{
low = mid + 1;
}
}while(low <= high);
pos = low;
}
// function for adding in any level
void addtosort(void **&start, void *pnew, int pos)
{
int count = ((int*)start)[COUNT_POS];
int size = ((int*)start)[SIZE_POS];
if(count == size)
{
ExpandArrPtr(start, size, count);
}
if(pos == count)
{
start[pos] = pnew;
}
else
{
for(int i = count;i >= pos;i--)
{
start[i+1] = start[i];
}
start[pos] = pnew;
}
count++;
((int*)start)[COUNT_POS] = count;
}
void add_goods(void **&Start, goods * Pnew)
{
int pos;
bool find;
bin_search((((shop*)(Start))->sublevel), Pnew->name, pos, find, compare_goods);
addtosort((((shop*)(Start))->sublevel), Pnew, pos);
}
// finding the item in second level to add
void find_place(QString key)
{
int pos;
bool find;
int count = ((int*)Start)[COUNT_POS];
for(int i = 0;i < count;i++)
{
bin_search(((net*)(Start)[i])->sublevel, key, pos, find, compare_shop);
if(find)
{
goods * Pnew = new goods;
Pnew->date = "foo"
Pnew->name = "bar"
add_goods(((net*)(Start)[pos])->sublevel, Pnew);
break;
}
}
}
What can cause such problem?
I have a struct that looks like this:
// A lexical scope that keeps track of every declared variable
// in a function
struct LexState
{
// A map containing the index of a variable in it's function
// The key is the variable name
std::unordered_map<std::string, int> _vars;
Function *_function;
LexState *_parent;
};
This is the code using the struct:
#define DD(msg) std::cout << "Debug: " << msg << '\n'
#define DD1(msg, p1) std::cout << "Debug: " << msg << p1 << '\n'
#define DD2(msg, p1, p2) std::cout << "Debug: " << msg << p1 << p2 << '\n'
// A lexical scope that keeps track of every declared variable
// in a function
struct LexState
{
// A map containing the index of a variable in it's function
// The key is the variable name
std::unordered_map<std::string, int> _vars;
Function *_function;
LexState *_parent;
LexState(LexState *parent, Function *function)
{
_parent = parent;
_function = function;
}
Value *SearchVar(char *name)
{
if (_parent == nullptr)
{
return nullptr;
}
std::string str(name);
auto var = _parent->_vars.find(str);
if (var == _parent->_vars.end())
{
return _parent->SearchVar(name);
}
return _function->GetLocalVar(var->second)->GetValue();
}
};
class Compiler
{
public:
State *_state;
Function *_current_function;
GC *_gc;
LexState *_ls;
Compiler(State *state) :
_state(state)
{
_current_function = nullptr;
_gc = state->GetGC();
_current_function = new Function(nullptr);
_state->_main_function = _current_function;
_ls = nullptr;
}
void PushFunction()
{
Function *new_function = new Function(_current_function);
_current_function = new_function;
LexState *new_ls = new LexState(_ls, new_function);
// even now, right after creating new_ls, new_ls->_vars is 0
printf("%p\n", &new_ls->_vars);
_ls = new_ls;
}
void PopFunction()
{
_current_function = _current_function->_parent;
LexState *parent = _ls->_parent;
delete _ls;
_ls = parent;
}
int DeclareVar(const Symbol *node)
{
assert(node->_type == NODE_SYMBOL);
DD("Declaring variable");
auto token = node->_token;
char name[token->len + 1];
memcpy(name, token->pos, token->len);
name[token->len] = '\0';
int idx = _current_function->AddLocalVar(name);
std::string key(name);
printf("%p\n", &_ls->_vars);
if (_ls != nullptr)
_ls->_vars.insert(std::make_pair(key, idx));
else
DD("LexState nullptr");
DD("Variable declared");
return idx;
}
void Compile(const Node *node)
{
switch (node->_type)
{
case NODE_CHUNK:
CompileChunk((Chunk *)node);
break;
case NODE_BLOCK:
CompileBlock((Block *)node);
break;
case NODE_FUNCTION_DEF:
CompileFunctionDef((FunctionDef *)node);
break;
case NODE_CONDITIONAL:
CompileConditional((ConditionalStatement *)node);
break;
case NODE_BINARY_EXPR:
CompileBinaryExpr((BinaryExpr *)node);
break;
case NODE_UNARY_EXPR:
CompileUnaryExpr((UnaryExpr *)node);
break;
case NODE_SYMBOL:
CompileSymbol((Symbol *)node);
break;
case NODE_STRING_LITERAL:
CompileStringLiteral((StringLiteral *)node);
break;
case NODE_BOOL_LITERAL:
CompileBoolLiteral((BoolLiteral *)node);
break;
case NODE_INT_LITERAL:
CompileIntLiteral((IntLiteral *)node);
break;
}
}
void CompileChunk(const Chunk *chunk)
{
Compile(chunk->_block);
AddCode(OP_HALT);
}
void CompileBlock(const Block *block)
{
std::vector<Node *> vec = block->_vec;
for (auto it = vec.begin(); it != vec.end(); it++)
{
Compile(*it);
}
}
void CompileFunctionDef(const FunctionDef *func)
{
Value v;
int f = AddConstant(v);
AddCode(OP_PUSH, f);
Value *vp = _current_function->GetConstant(f);
if (func->_name)
{
int fvar = DeclareVar((Symbol *)func->_name);
AddCode(OP_STOR_LOCAL, fvar);
}
ArgList *argsnode = (ArgList *)func->_args;
auto args = argsnode->_vec;
int argcount = args.size();
PushFunction();
auto closure = new Closure(_current_function);
closure->_argcount = argcount;
std::cout << argcount << '\n';
vp->_closure = closure;
vp->_type = VALUE_CLOSURE;
// Compiling inside function
// Arguments are compiled in reserved order, because in the function call
// the passed arguments will be pushed in the order they are passed
for (auto it = args.rbegin(); it != args.rend(); it++)
{
int var = DeclareVar((Symbol *)*it);
AddCode(OP_STOR_LOCAL, var);
}
if (func->_guard)
{
Compile(func->_guard);
}
else
{
Compile(func->_body);
}
AddCode(OP_RETURN);
// End function
PopFunction();
}
void CompileConditional(const ConditionalStatement *node)
{
auto function = _current_function;
Compile(node->_condition);
int cond_res_idx = function->AddLocalVar();
AddCode(OP_DUP);
// Store the condition result into an internal variable
AddCode(OP_STOR_LOCAL, cond_res_idx);
AddCode(OP_DUP);
int true_jmp = AddCode(OP_JMP_T, 0);
int false_jmp = AddCode(OP_JMP_F, 0);
// Save index of the first code of the block
int block_idx = function->_code.size();
// Jump to block when condition is true
function->ChangeCode(true_jmp, block_idx);
Compile(node->_expr1);
AddCode(OP_PUSH_LOCAL, cond_res_idx);
// Jump to the end of the whole if-elif-else statement
// if the condition result was true
int exit_jmp = AddCode(OP_JMP_T, 0);
// Save index of the first code after this statement
int right_idx = function->_code.size();
function->ChangeCode(false_jmp, right_idx);
if (node->_expr2 != nullptr)
{
Compile(node->_expr2);
}
else
{
AddCode(OP_PUSH_NIL);
}
int end_idx = function->_code.size();
function->ChangeCode(exit_jmp, end_idx);
}
void CompileBinaryExpr(const BinaryExpr *expr)
{
auto function = _current_function;
auto token = expr->_op->type;
if (token == TOKEN_ASSIGN)
{
if (expr->_left->_type == NODE_SYMBOL)
{
int var = DeclareVar((Symbol *)expr->_left);
Compile(expr->_right);
AddCode(OP_STOR_LOCAL, var);
return;
}
}
// A function call
if (token == TOKEN_LEFTPAREN)
{
ArgList *arglist = (ArgList *)expr->_right;
auto args = arglist->_vec;
int argcount = args.size();
// A function call cannot have more than 255 arguments
assert(argcount < 256);
for (auto it = args.begin(), end = args.end();
it != end; it++)
{
Compile(*it);
}
Compile(expr->_left);
AddCode(OP_CALL, argcount);
return;
}
Compile(expr->_left);
// Both 'and' and 'or' expressions does short circuit
if (token == TOKEN_BOOL_AND ||
token == TOKEN_BOOL_OR)
{
AddCode(OP_DUP);
OpType op = (token == TOKEN_BOOL_AND) ? OP_JMP_F : OP_JMP_T;
int idx = AddCode(op, function->_ip + 1);
Compile(expr->_right);
int next = function->_code.size();
uint32_t instr = function->_code[idx];
function->ChangeCode(idx, next);
return;
}
// No need for lazy evaluation, compile normally
Compile(expr->_right);
switch (expr->_op->type)
{
case TOKEN_ADD:
AddCode(OP_ADD);
break;
case TOKEN_SUB:
AddCode(OP_SUB);
break;
case TOKEN_MUL:
AddCode(OP_MUL);
break;
case TOKEN_DIV:
AddCode(OP_DIV);
break;
case TOKEN_POW:
AddCode(OP_POW);
break;
case TOKEN_AND:
AddCode(OP_AND);
break;
case TOKEN_OR:
AddCode(OP_OR);
break;
case TOKEN_XOR:
AddCode(OP_XOR);
break;
case TOKEN_LT:
AddCode(OP_LT);
break;
case TOKEN_GT:
AddCode(OP_GT);
break;
case TOKEN_LTEQ:
AddCode(OP_LTEQ);
break;
case TOKEN_GTEQ:
AddCode(OP_GTEQ);
break;
case TOKEN_SHIFT_L:
AddCode(OP_SHIFT_L);
break;
case TOKEN_SHIFT_R:
AddCode(OP_SHIFT_R);
break;
}
}
void CompileUnaryExpr(const UnaryExpr *expr)
{
Compile(expr->_right);
switch (expr->_token->type)
{
case TOKEN_SUB:
AddCode(OP_NEGATE);
break;
case TOKEN_NOT:
AddCode(OP_NOT);
break;
case TOKEN_BOOL_NOT:
AddCode(OP_BOOL_NOT);
break;
}
}
// This function gets called only when it's a reference
void CompileSymbol(const Symbol *node)
{
auto token = node->_token;
char name[token->len + 1];
memcpy(name, token->pos, token->len);
name[token->len] = '\0';
DD1("Searching reference: ", name);
Value *upvalue = _ls->SearchVar(name);
if (upvalue)
{
int idx = _current_function->AddUpValue(upvalue);
AddCode(OP_PUSH_UPVALUE, idx);
return;
}
int idx = _current_function->GetLocalVarIndex(name);
AddCode(OP_PUSH_LOCAL, idx);
}
void CompileStringLiteral(const StringLiteral *sl)
{
Value v(sl->_token->str, sl->_token->len);
AddCode(OP_PUSH, AddConstant(v));
}
void CompileBoolLiteral(const BoolLiteral *bl)
{
Value v(bl->_token->type == TOKEN_TRUE);
AddCode(OP_PUSH, AddConstant(v));
}
void CompileIntLiteral(const IntLiteral *il)
{
Value v(il->_token->num);
AddCode(OP_PUSH, AddConstant(v));
}
int AddCode(OpType code)
{
return _current_function->AddCode(code);
}
int AddCode(OpType code, int a)
{
return _current_function->AddCode(code, a);
}
int AddConstant(const Value &v)
{
return _current_function->AddConstant(v);
}
};
The program outputs:
Declaring variable
0
It crashes before the DD("Variable declared") part.
Even though i'm new to C++, I'm pretty sure I don't need to allocate the unordered map myself, right? As it's not a pointer, it will be allocated when I do new LexState
So is there any initialization/allocation I am forgetting?
%i is not the right format specifier to use to print a pointer. You are most likely getting the output that represents a truncated value of the pointer. Use %p instead.
printf("%p\n", &state->_vars);
I don't see anything wrong using state->_vars. See working code at http://ideone.com/YAJK5K.
I got this implementation for maximum matching off the net and is trying to give its input through main class. But I am getting zero for all the places in match. What am I doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <queue>
using namespace std;
void add_edge(int u, int v);
void edmonds();
struct edge {
int v, nx;
};
const int MAXN = 1000, MAXE = 2000;
edge graph[MAXE];
int last[MAXN], match[MAXN], px[MAXN], base[MAXN], N, M, edges;
bool used[MAXN], blossom[MAXN], lused[MAXN];
int main ()
{
// return 0;
add_edge(1,4);
add_edge(1,5);
add_edge(1,6);
add_edge(2,5);
add_edge(2,7);
add_edge(3,4);
add_edge(4,1);
add_edge(4,3);
add_edge(5,1);
add_edge(5,2);
add_edge(6,1);
add_edge(7,2);
edmonds();
cout << match[0];
cout << match[1];
cout << match[2];
cout << match[3];
cout << match[4];
cout << match[5];
cout << match[6];
}
inline void add_edge(int u, int v) {
graph[edges] = (edge) {v, last[u]};
last[u] = edges++;
graph[edges] = (edge) {u, last[v]};
last[v] = edges++;
}
void mark_path(int v, int b, int children) {
while (base[v] != b) {
blossom[base[v]] = blossom[base[match[v]]] = true;
px[v] = children;
children = match[v];
v = px[match[v]];
}
}
int lca(int a, int b) {
memset(lused, 0, N);
while (1) {
lused[a = base[a]] = true;
if (match[a] == -1)
break;
a = px[match[a]];
}
while (1) {
b = base[b];
if (lused[b])
return b;
b = px[match[b]];
}
}
int find_path(int root) {
memset(used, 0, N);
memset(px, -1, sizeof(int) * N);
for (int i = 0; i < N; ++i)
base[i] = i;
used[root] = true;
queue<int> q;
q.push(root);
register int v, e, to, i;
while (!q.empty()) {
v = q.front(); q.pop();
for (e = last[v]; e >= 0; e = graph[e].nx) {
to = graph[e].v;
if (base[v] == base[to] || match[v] == to)
continue;
if (to == root || (match[to] != -1 && px[match[to]] != -1)) {
int curbase = lca(v, to);
memset(blossom, 0, N);
mark_path(v, curbase, to);
mark_path(to, curbase, v);
for (i = 0; i < N; ++i)
if (blossom[base[i]]) {
base[i] = curbase;
if (!used[i]) {
used[i] = true;
q.push(i);
}
}
} else if (px[to] == -1) {
px[to] = v;
if (match[to] == -1)
return to;
to = match[to];
used[to] = true;
q.push(to);
}
}
}
return -1;
}
void build_pre_matching() {
register int u, e, v;
for (u = 0; u < N; ++u)
if (match[u] == -1)
for (e = last[u]; e >= 0; e = graph[e].nx) {
v = graph[e].v;
if (match[v] == -1) {
match[u] = v;
match[v] = u;
break;
}
}
}
void edmonds() {
memset(match, 0xff, sizeof(int) * N);
build_pre_matching();
register int i, v, pv, ppv;
for (i = 0; i < N; ++i)
if (match[i] == -1) {
v = find_path(i);
while (v != -1) {
pv = px[v], ppv = match[pv];
match[v] = pv, match[pv] = v;
v = ppv;
}
}
}
You set elements of match in two locations: In build_pre_matching() and in edmonds(). In both of these cases, no change will happen if match[x] for some index x isn't -1. The only other place elements of match get a value is during static initialization where the values get zero initialized. Since the initial value is zero and the values are only ever changed if at least one of them happens to be -1, I would expect that the values retain the value 0.
You might want to use something like
std::fill(std::begin(match), std::end(match), -1);
at a strategic location since you seem to assume that the values are initially -1. Of course, you also should consider the idea of not using global variables because this doesn't scale and works really badly in a multi-threaded program.