首页 > 代码库 > Codility上的问题 (40)Sulphur 2014

Codility上的问题 (40)Sulphur 2014

给定n个绳子,每个绳子编号0..N - 1。每个绳子下面挂一个重物,每个绳子另外一端(不挂重物的那端),可以挂在其他的绳子上,也可以挂在顶端(只有一个顶端),这些绳子形成一个树。树的结构由数组A,B,C,给出。其中A表示绳子的承受力,如果挂载绳子下的总重量大于绳子的承受力,绳子会断。B表示绳子一端挂的重物的重量,C表示该绳子另外一端挂的绳子的编号(C[i] < i)。挂绳子的顺序就是编号从小到大的顺序,求最多挂几根绳子而不会由绳子断掉?
例如:
    A[0] = 5    B[0] = 2    C[0] = -1
    A[1] = 3    B[1] = 3    C[1] = 0
    A[2] = 6    B[2] = 1    C[2] = -1
    A[3] = 3    B[3] = 1    C[3] = 0
    A[4] = 3    B[4] = 2    C[4] = 3


返回3,因为挂到第4根的时候(编号为3),绳子会断 (0号断了)。


又如:

   A[0] = 4    B[0] = 2    C[0] = -1
   A[1] = 3    B[1] = 2    C[1] = 0
   A[2] = 1    B[2] = 1    C[2] = 1

返回2。


函数头部:

int solution(vector<int> &A, vector<int> &B, vector<int> &C)


数据范围:

N [0..10^5]

A数组数据范围是[1..10^6]

B数组数据范围是[1..5000]


要求复杂度: 时间 O(NlogN) 空间O(N)


分析:这个题似乎可以像Tarjan的LCA算法那样求,但是很麻烦,我也没细想…… 有一个显然的简单思路,就是二分。二分绳子数,然后只考虑编号<= mid的那些绳子,看看这个树会不会有断掉的绳子,决定二分的方向……

总之,不是一个难题,描述很麻烦,直接上代码:

// you can use includes, for example:
// #include <algorithm>

// you can write to stdout for debugging purposes, e.g.
// cout << "this is a debug message" << endl;

bool dfs(int x,int m,vector<vector<int> > &con, vector<int> &A,vector<int> &B, vector<int> &w) {
    w[x] = B[x];
    for (int i = 0; (i < con[x].size()) && (con[x][i] < m); ++i) {
        if (!dfs(con[x][i], m, con, A, B, w)) {
            return false;
        }
        w[x] += w[con[x][i]];
    }
    return w[x] <= A[x];
}

bool can(int m,vector<vector<int> > &con,vector<int> &A,vector<int> &B) {
vector<int> w(m,-1);
    for (int i = 0; i < m; ++i) {
        if ((w[i] < 0) && (!dfs(i,m, con, A, B,w))) {
            return false;
        }
    }
    return true;
}

int solution(vector<int> &A, vector<int> &B, vector<int> &C) {
    // write your code in C++11
    int n = A.size();
    vector<vector<int> > con(n);
    for (int i = 0; i < n; ++i) {
        if (C[i] >= 0) {
            con[C[i]].push_back(i);
        }
    }
    int left = 1, right = n;
    while (left <= right) {
        int mid = (left + right) >> 1;
        if (can(mid,con, A, B)) {
            left = mid + 1;
        }
        else {
            right = mid - 1;
        }
    }
    return left - 1;
}



Codility上的问题 (40)Sulphur 2014