学习笔记
//非常漂亮地把可能的雷都踩了,算是吃了这类题的教训
//参考了大佬的思路
//萌新代码 谨慎观看
/*2024.2.21 邻接表*/
//怎么知道什么时候可以拖延?
//先拓扑找到最早结束时间,记录排序
//根据排序,反向回溯求出最晚结束时间
//WA: 检测是否为重复路径问题
//WA: 也不是输出字典序问题
//WA: 其实最关键的错误是没有处理好不与任何点产生链接的孤立点
//ps:后面测试了一下,前俩个WA猜测都不会导致WA,不过,小心为上~
#include<iostream>
#include<cstring>
#include<string>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
int n, m;
const int N = 3e5 + 10;
struct Node {
int late = 0x3f3f3f3f;
int zao;
int cost;
int in = 0;
}node[N];
vector<int> arr[N];
int main() {
ios::sync_with_stdio(0);
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> node[i].cost;
node[i].zao = node[i].cost;
}
map<pair<int, int>, bool> g;
for (int i = 1; i <= m; i++) {
int u, v;
cin >> u >> v;
if (g[{u, v}]) continue;
g[{u, v}] = 1;
arr[u].push_back(v);
node[v].in++;
}
queue<int> q;
//priority_queue<int> pq;
vector<int> qq;
for (int i = 1; i <= n; i++) {
if (node[i].in == 0) {
q.push(i);
}
}
int tim = 0;
while (q.size()) {
int pos = q.front();
q.pop();
qq.push_back(pos);//其实是把数组当栈表用了
tim = max(tim, node[pos].zao);//找出最少所需时间
for (int i = 0; i < arr[pos].size(); i++) {
int x = arr[pos][i];
node[x].in--;
node[x].zao = max(node[x].zao, node[x].cost + node[pos].zao);//最早结束时间
if (node[x].in == 0) {
q.push(x);
}
}
}
if (qq.size() != n) {
cout << -1 << "\n";
return 0;
}
for (int i = n-1; i >= 0; i--) {
int pos = qq[i];
node[pos].late = tim;//处理孤立点和没出度的点
for (int i = 0; i < arr[pos].size(); i++) {
int to = arr[pos][i];
int cost = node[to].cost;
node[pos].late = min(node[to].late - cost, node[pos].late);
}
}
vector<int> ans;
for (int i = 1; i <= n; i++) {
if (node[i].late > node[i].zao) ans.push_back(i);
}
sort(ans.begin(), ans.end());
cout << ans.size() << "\n";
for (int i : ans) {
cout << i << " ";
}cout << "\n";
return 0;
}