题意:
给出一个有向图,在这个图中选择一些点,这些点不能有边直接相连,并且每个点都能从某个选中的点不超过两步到达。
求任意一个方案。
分析:
也是非常简单的一道题。
任意找一个没被删除的点,删去它及它连向的点,对剩下的图继续做,直到删空为止。
然后按照删的反向顺序依次考虑:若所有连向它的点都没被选中,则选中这个点不会造成矛盾,直接选。否则就不选。这两种情况中,都能保证该点以及它的所有后继节点都是合法的。因为如果它的前驱节点没被选,就选中这个点,它的后继就能从这里出发,走一步到达。如果它前驱节点某一个被选了,那就能通过该点,走两步到达它的后继节点。
而且用的是反向的顺序,所以每次考虑一个点选不选的时候,它的所有前驱也一定是合法的。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 1000010
using namespace std;
bool used[MAXN],del[MAXN];
vector<int> a[MAXN],b[MAXN];
int n,m;
void dfs(int x){for(int i=x;i<=n;i++)if(del[i]==0){del[i]=1;for(int j=0;j<a[i].size();j++)del[a[i][j]]=1;dfs(i+1);used[i]=1;for(int j=0;j<b[i].size();j++)if(used[b[i][j]]==1){used[i]=0;break;}return ;}
}
int main(){SF("%d%d",&n,&m);int u,v;for(int i=1;i<=m;i++){SF("%d%d",&u,&v);a[u].push_back(v);b[v].push_back(u);}dfs(1);int cnt=0;for(int i=1;i<=n;i++)if(used[i]==1)cnt++;PF("%d\n",cnt);for(int i=1;i<=n;i++)if(used[i]==1)PF("%d ",i);
}