Loading

NWERC-2018 Brexit Negotiations 拓扑排序 思维

NWERC-2018 Brexit Negotiations 拓扑排序 思维

题意

\(n\)个会议要开,一段时间只能开一个会议。

每个会议有两个要素:会议时间和前置会议。

当前会议必须在前置会议结束后才能开。

每个会议的时间 = 当前会议时间 + 第几个会议

给出\(n,e,q\) 表示\(n\)个会议,\(e\)为当前会议的时间,\(q\)表示有\(q\)个前置会议。

\[1\leq n\leq 4 \times 10^5\\ 1\leq e \leq 10 ^6 \\ \]

分析

图论套路题。

很容易想到要进行拓扑排序,当时交上去了一发,wa了。

于是找到原因,发现这样找很可能会因为拓扑序,贪心的时候把其他更大的时间留在了后面,这显然是不合理的。

因此考虑反向拓扑,这样每次贪心的找更小的时间,这样就能保证最后的点一定是最大的时间,就能贪心的给他最小的附加时间。

如果正向拓扑,我们只能保证最后的时间一定是最小的时间。

代码

int n;
vector<int> e[maxn];
int inDeg[maxn];
int v[maxn];
bool vis[maxn];

struct node {
    int id;
    int val;
    node(int _id,int _val) {
        id = _id;
        val = _val;
    }
    friend bool operator < (const node& a, const node& b) {
        return a.val > b.val;
    }
};

int topo() {
    priority_queue<node> q;
    int tot = n;
    int res = 0;
    for (int i = 1; i <= n; i++)
        if (!inDeg[i]) q.push(node(i, v[i]));
    while (!q.empty()) {
        node u = q.top();
        q.pop();
        tot--;
        res = max(res, u.val + tot);
        for (int i = 0; i < e[u.id].size(); i++) {
            int y = e[u.id][i];
            inDeg[y]--;
            if (!inDeg[y]) q.push(node(y, v[y]));
        }
    }
    return res;
}

int main() {
    n = readint();
    for (int i = 1; i <= n; i++) {
        int tmp = readint();
        v[i] = tmp;
        int q = readint();
        for (int j = 0; j < q; j++) {
            int u = readint();
            inDeg[u]++;
            e[i].push_back(u);
        }
    }
    Put(topo());
}
posted @ 2020-10-01 19:16  MQFLLY  阅读(362)  评论(0编辑  收藏  举报