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());
}