题面
题解
看哪些事件不发生也对答案没有影响
假如说这件事不发生, 那么他的前驱都不会发生
然后把所有入度为零并且不是这件事的前驱的点全部设为发生, BFS 一遍, 看那 M 个是否都能发生
若能, 则该事件不一定发生
若不能, 该事件一定发生
复杂度 (O(nm))
Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
const int N = 100005;
using namespace std;
int n, m, t, head[N], head1[N], cnt, tot, d[N], vis[N], hp[N], ck[N], ans[N];
struct edge { int to, nxt; } e[N], E[N];
queue<int> q;
template < typename T >
inline T read()
{
T x = 0, w = 1; char c = getchar();
while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * w;
}
inline void adde(int u, int v)
{
e[++cnt] = (edge) { v, head[u] }, head[u] = cnt;
E[++tot] = (edge) { u, head1[v] }, head1[v] = tot;
}
bool check(int x)
{
q.push(x), vis[x] = ++cnt;
while(!q.empty())
{
int u = q.front(); q.pop();
for(int v, i = head1[u]; i; i = E[i].nxt)
if(vis[v = E[i].to] != cnt) vis[v] = cnt, q.push(v);
}
for(int i = 1; i <= t; i++)
if(vis[hp[i]] == cnt) return 1;
for(int i = 1; i <= n; i++)
if(!d[i] && vis[i] != cnt) q.push(i), vis[i] = cnt;
while(!q.empty())
{
int u = q.front(); q.pop();
for(int v, i = head[u]; i; i = e[i].nxt)
if(vis[v = e[i].to] != cnt) vis[v] = cnt, q.push(v);
}
for(int i = 1; i <= t; i++)
if(vis[hp[i]] != cnt) return 1;
return 0;
}
int main()
{
n = read <int> (), m = read <int> (), t = read <int> ();
for(int u, v, i = 1; i <= m; i++)
{
u = read <int> (), v = read <int> ();
adde(u, v), d[v]++;
}
cnt = 0;
for(int i = 1; i <= t; i++)
ck[hp[i] = read <int> ()] = 1;
for(int i = 1; i <= n; i++)
if(ck[i] || check(i)) ans[++ans[0]] = i;
for(int i = 1; i <= ans[0]; i++)
printf("%d%c", ans[i], i == ans[0] ? '
' : ' ');
return 0;
}