题意:
找出来一个点集S 使得S中的点不能互相通过一步到达
并且S中的点 可以在小于等于2的步数下到达所有的点
要父结点 不要子结点 这样就求出来一个点集S‘ 而S'中可能存在 v -> u 这样的路
所以从后向前遍历 结点 把S’中的点的子结点且在S‘中的点 再从S'中去除掉
关于为什么从后向前 而不是从前向后 :
因为S’中剩余的是 v -> u 从后向前可以保证隔一个标记一个
而从前向后的话 可能使得S‘中的点到达其它点的步数大于二 画图想一下就出来了
#include <bits/stdc++.h> #define mem(a, b) memset(a, b, sizeof(a)) using namespace std; const int maxn = 1e6 + 10, INF = 0x7fffffff; int head[maxn], vis[maxn], chose[maxn]; int cnt; vector<int> v; struct node { int u, v, next; }Node[maxn]; void add(int u, int v) { Node[cnt].u = u; Node[cnt].v = v; Node[cnt].next = head[u]; head[u] = cnt++; } int main() { int n, m; mem(head, -1); cnt = 0; scanf("%d%d", &n, &m); int a, b; for(int i=0; i<m; i++) { scanf("%d%d", &a, &b); add(a, b); } for(int i=1; i<=n; i++) { if(!vis[i]) { vis[i] = 1, chose[i] = 1; for(int j=head[i]; j!=-1; j=Node[j].next) { node e = Node[j]; vis[e.v] = 1; } } } for(int i=n; i>0; i--) if(chose[i]) for(int j=head[i]; j!=-1; j=Node[j].next) { node e = Node[j]; chose[e.v] = 0; } int res = 0; for(int i=1; i<=n; i++) if(chose[i]) res++; cout<< res <<endl; int ans = 0; for(int i=1; i<=n; i++) if(chose[i]) if(ans++) cout<< " " << i; else cout<< i ; cout<<endl; return 0; }