Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <vector>
- #include <cstdio>
- using namespace std;
- #define trav(x, y, z) for(typeof(x) z = x; z != y; z++)
- int bestSolution = 10000000;
- int k;
- typedef pair<int, int> path; //weight, distance
- vector< vector<path > > adj;
- void combine(vector<path> *result, vector<path> *left, vector<path> *right){
- size_t li = 0;
- int ri = right->size()-1;
- while(li != left->size() && ri != -1){
- int weight = (*left)[li].first + (*right)[ri].first;
- if(weight == k){
- int length = (*left)[li].second + (*right)[ri].second;
- if(length < bestSolution){
- bestSolution = length;
- }
- li++;
- } else if(weight < k){
- li++;
- } else {
- ri--;
- }
- }
- li = 0;
- ri = 0;
- for(size_t i = 0; i<left->size()+right->size(); i++){
- if(li == left->size() || (ri != right->size() && (*right)[ri].first < (*left)[li].first)){
- result->push_back((*right)[ri++]);
- } else if(ri == right->size() || (li != left->size() && (*left)[li].first < (*right)[ri].first)){
- result->push_back((*left)[li++]);
- } else {
- if((*right)[ri].second < (*left)[li].second){
- result->push_back((*right)[ri++]);
- } else {
- result->push_back((*left)[li++]);
- }
- }
- }
- }
- vector<path> divide(vector<vector<path> > *paths, int a, int b){
- if(a == b) return (*paths)[a];
- //dela och merga
- vector<path> lower = divide(paths, a, (a+b)/2);
- vector<path> upper = divide(paths, (a+b)/2+1, b);
- vector<path> result;
- combine(&result, &lower, &upper);
- return result;
- }
- void append(vector<path> *res, vector<path> *result, int dist){
- trav(result->begin(), result->end(), it){
- path prev = *it;
- res->push_back(path(prev.first+dist, prev.second+1));
- }
- }
- vector<path> solve(int n, int from, int dist){
- vector< vector<path > > paths;
- trav(adj[n].begin(), adj[n].end(), it){
- path p = (*it);
- if(p.first == from) continue;
- paths.push_back(solve(p.first, n, p.second));
- }
- vector<path> single;
- single.push_back(path(0, 0));
- paths.push_back(single);
- int b = paths.size();
- if(b == 1){
- vector<path> result;
- append(&result, &paths[0], dist);
- return result;
- }
- vector<path> low = divide(&paths, 0, (b-1)/2);
- vector<path> high = divide(&paths, ((b-1)/2)+1, b-1);
- vector<path> result;
- combine(&result, &low, &high);
- vector<path> appended;
- append(&appended, &result, dist);
- return appended;
- }
- int best_path(int n, int kk, int h[][2], int l[]){
- k = kk;
- bestSolution = 10000000;
- adj.clear();
- adj.resize(n);
- for(int i = 0; i < n-1; i++){
- int f = h[i][0];
- int t = h[i][1];
- adj[f].push_back(path(t, l[i]));
- adj[t].push_back(path(f, l[i]));
- }
- solve(0, -1, 0);
- if(bestSolution == 10000000) return -1;
- return bestSolution;
- }
- void case1(){
- int n = 4;
- int k = 3;
- int h[][2] = {
- {0, 1},
- {1, 2},
- {1, 3}
- };
- int l[] = {1, 2, 4};
- printf("%d\n", best_path(n, k, h, l));
- }
- void case2(){
- int n = 3;
- int k = 3;
- int h[][2] = {
- {0, 1},
- {1, 2}
- };
- int l[] = {1, 1};
- printf("%d\n", best_path(n, k, h, l));
- }
- void case3(){
- int n = 11;
- int k = 12;
- int h[][2] = {
- {0, 1},
- {0, 2},
- {2, 3},
- {3, 4},
- {4, 5},
- {0, 6},
- {6, 7},
- {6, 8},
- {8, 9},
- {8, 10},
- };
- int l[] = {3, 4, 5, 4, 6, 3, 2, 5, 6, 7};
- printf("%d\n", best_path(n, k, h, l));
- }
- int main(){
- case1();
- case2();
- case3();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement