int main() { // read in the number of vertices and edges int n, m; scanf( "%d %d", &n, &m ); // initialize the union-find data structure vertex* vertices = (vertex*)calloc(n,sizeof(vertex)); for( int i = 0; i < n; ++i ) { vertices[i].boss = i; vertices[i].size = 1; vertices[i].set = (int*)malloc(sizeof(int)); vertices[i].set[0] = i; } // read in and initialize the edge list edge* edges = (edge*)calloc(m, sizeof(edge)); int* T = (int*)calloc(m, sizeof(int)); for( int i = 0; i < m; ++i ) { edge* e = &edges[i]; scanf( "%d %d %lf %d", &e->u, &e->v, &e->w, &e->f ); } // mergesort the edges mrgsrt(edges, m, sizeof(edge), edge_cmp); #ifdef DEBUG for( int i = 0; i < m; ++i ) { printf( "%d<->%d: %f (%d)\n", edges[i].u, edges[i].v, edges[i].w, edges[i].f ); } #endif int tindex = 0; // start kruskal's algorithm for( int i = 0; i < m; ++i ) { edge* e = &edges[i]; // check to see if the addition of the current edge produces a cycle if( find(vertices,e->u) == find(vertices,e->v) ) { if( e->f ) { //if this edge is in f than we have a problem... printf( "-1\n" ); break; } } else { // add the edge to the chosen edges list T[tindex++] = i; unionize(vertices,n,e->u,e->v); } } if( tindex == n - 1 ) { // determine the total weight of all the added edges double weight = 0; for( int i = 0; i < tindex; ++i ) { weight += edges[T[i]].w; } // print the weight printf( "%d\n", (int)weight ); } end: // cleanup memory! for( int i = 0; i < n; ++i ) { free(vertices[i].set); } free(vertices); free(edges); free(T); return 0; }
// static void IndexBoundsBuilder::translate(const MatchExpression* expr, const BSONElement& elt, OrderedIntervalList* oilOut, bool* exactOut) { oilOut->name = elt.fieldName(); bool isHashed = false; if (mongoutils::str::equals("hashed", elt.valuestrsafe())) { isHashed = true; } if (isHashed) { verify(MatchExpression::EQ == expr->matchType() || MatchExpression::MATCH_IN == expr->matchType()); } if (MatchExpression::ELEM_MATCH_VALUE == expr->matchType()) { OrderedIntervalList acc; bool exact; translate(expr->getChild(0), elt, &acc, &exact); if (!exact) { *exactOut = false; } for (size_t i = 1; i < expr->numChildren(); ++i) { OrderedIntervalList next; translate(expr->getChild(i), elt, &next, &exact); if (!exact) { *exactOut = false; } intersectize(next, &acc); } for (size_t i = 0; i < acc.intervals.size(); ++i) { oilOut->intervals.push_back(acc.intervals[i]); } if (!oilOut->intervals.empty()) { std::sort(oilOut->intervals.begin(), oilOut->intervals.end(), IntervalComparison); } } else if (MatchExpression::EQ == expr->matchType()) { const EqualityMatchExpression* node = static_cast<const EqualityMatchExpression*>(expr); translateEquality(node->getData(), isHashed, oilOut, exactOut); } else if (MatchExpression::LTE == expr->matchType()) { const LTEMatchExpression* node = static_cast<const LTEMatchExpression*>(expr); BSONElement dataElt = node->getData(); // Everything is <= MaxKey. if (MaxKey == dataElt.type()) { oilOut->intervals.push_back(allValues()); *exactOut = true; return; } BSONObjBuilder bob; bob.appendMinForType("", dataElt.type()); bob.appendAs(dataElt, ""); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); oilOut->intervals.push_back(makeRangeInterval(dataObj, true, true)); // XXX: only exact if not (null or array) *exactOut = true; } else if (MatchExpression::LT == expr->matchType()) { const LTMatchExpression* node = static_cast<const LTMatchExpression*>(expr); BSONElement dataElt = node->getData(); // Everything is <= MaxKey. if (MaxKey == dataElt.type()) { oilOut->intervals.push_back(allValues()); *exactOut = true; return; } BSONObjBuilder bob; bob.appendMinForType("", dataElt.type()); bob.appendAs(dataElt, ""); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); QLOG() << "data obj is " << dataObj.toString() << endl; oilOut->intervals.push_back(makeRangeInterval(dataObj, true, false)); // XXX: only exact if not (null or array) *exactOut = true; } else if (MatchExpression::GT == expr->matchType()) { const GTMatchExpression* node = static_cast<const GTMatchExpression*>(expr); BSONElement dataElt = node->getData(); // Everything is > MinKey. if (MinKey == dataElt.type()) { oilOut->intervals.push_back(allValues()); *exactOut = true; return; } BSONObjBuilder bob; bob.appendAs(node->getData(), ""); bob.appendMaxForType("", dataElt.type()); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); oilOut->intervals.push_back(makeRangeInterval(dataObj, false, true)); // XXX: only exact if not (null or array) *exactOut = true; } else if (MatchExpression::GTE == expr->matchType()) { const GTEMatchExpression* node = static_cast<const GTEMatchExpression*>(expr); BSONElement dataElt = node->getData(); // Everything is >= MinKey. if (MinKey == dataElt.type()) { oilOut->intervals.push_back(allValues()); *exactOut = true; return; } BSONObjBuilder bob; bob.appendAs(dataElt, ""); bob.appendMaxForType("", dataElt.type()); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); oilOut->intervals.push_back(makeRangeInterval(dataObj, true, true)); // XXX: only exact if not (null or array) *exactOut = true; } else if (MatchExpression::REGEX == expr->matchType()) { const RegexMatchExpression* rme = static_cast<const RegexMatchExpression*>(expr); translateRegex(rme, oilOut, exactOut); } else if (MatchExpression::MOD == expr->matchType()) { BSONObjBuilder bob; bob.appendMinForType("", NumberDouble); bob.appendMaxForType("", NumberDouble); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); oilOut->intervals.push_back(makeRangeInterval(dataObj, true, true)); *exactOut = false; } else if (MatchExpression::TYPE_OPERATOR == expr->matchType()) { const TypeMatchExpression* tme = static_cast<const TypeMatchExpression*>(expr); BSONObjBuilder bob; bob.appendMinForType("", tme->getData()); bob.appendMaxForType("", tme->getData()); BSONObj dataObj = bob.obj(); verify(dataObj.isOwned()); oilOut->intervals.push_back(makeRangeInterval(dataObj, true, true)); *exactOut = false; } else if (MatchExpression::MATCH_IN == expr->matchType()) { const InMatchExpression* ime = static_cast<const InMatchExpression*>(expr); const ArrayFilterEntries& afr = ime->getData(); *exactOut = true; // Create our various intervals. bool thisBoundExact = false; for (BSONElementSet::iterator it = afr.equalities().begin(); it != afr.equalities().end(); ++it) { translateEquality(*it, isHashed, oilOut, &thisBoundExact); if (!thisBoundExact) { *exactOut = false; } } for (size_t i = 0; i < afr.numRegexes(); ++i) { translateRegex(afr.regex(i), oilOut, &thisBoundExact); if (!thisBoundExact) { *exactOut = false; } } // XXX: what happens here? if (afr.hasNull()) { } // XXX: what happens here as well? if (afr.hasEmptyArray()) { } unionize(oilOut); } else if (MatchExpression::GEO == expr->matchType()) { const GeoMatchExpression* gme = static_cast<const GeoMatchExpression*>(expr); // Can only do this for 2dsphere. if (!mongoutils::str::equals("2dsphere", elt.valuestrsafe())) { warning() << "Planner error trying to build geo bounds for " << elt.toString() << " index element."; verify(0); } const S2Region& region = gme->getGeoQuery().getRegion(); ExpressionMapping::cover2dsphere(region, oilOut); *exactOut = false; } else { warning() << "Planner error, trying to build bounds for expr " << expr->toString() << endl; verify(0); } }
WordNode * processQuery(char * query, HashTable *index){ //TODO: eat leftover from the buffer if (NULL == strchr(query, '\n')){ printf("Whoa there. You entered too many characters. Query must exit."); return NULL; } //if there is more than 1000 characters. didn't handle yet. printf("\n"); // get first word in query char * pch = strtok(query," \n"); if(pch == NULL){ fprintf(stdout, "No input specified. \n"); printf("QUERY>: "); return init_list(); } if ((strcmp("OR", pch) == 0) || (strcmp("AND",pch) == 0)) { fprintf(stderr, "Invalid input. AND/OR cannot start your search query. please use a non-operator word to search \n"); printf("QUERY>: "); return NULL; } //initialize search results int or = -1; //set to negative one on first run WordNode * search_results = NULL; WordNode * tmp_list = NULL; // go through rest of the query string while (pch != NULL) { //check if OR or AND if (strcmp("OR", pch) == 0) { // printf("or here"); or = 1; pch = strtok (NULL, " \n"); continue; } else if (strcmp("AND", pch) == 0) { // printf("and here"); or = 0; pch = strtok (NULL, " \n"); continue; } // switch to lowercase NormalizeWord(pch); if(or == 1){ // fprintf(stdout,"Doing OR"); if (search_results) { // if there has been an OR before, now unionize search_results = unionize(search_results, tmp_list); } else { // only the first or // need to hold on to previous list search_results = tmp_list; } // set tmp_list to the new list word tmp_list = make_copy((WordNode *) get_value(pch ,index)); } else if (or == 0){ // printf("Doing AND"); // get intersect tmp_list = intersection(tmp_list, make_copy(get_value(pch ,index))); } else { // first run (or = -1) tmp_list = make_copy((WordNode *) get_value(pch ,index)); // if(tmp_list){ // fprintf(stderr, "GOT SOMETHING!!\n"); // if (tmp_list->head) // fprintf(stderr, "here is something %d", tmp_list->head->docID); // } } or = 0; // "marks AND for next" pch = strtok (NULL, " \n"); } //end search loop // in the end, unionize the two lists! search_results = unionize(search_results, tmp_list); return search_results; }
// static void IndexBoundsBuilder::translateAndUnion(const MatchExpression* expr, const BSONElement& elt, OrderedIntervalList* oilOut, bool* exactOut) { translate(expr, elt, oilOut, exactOut); unionize(oilOut); }