版权声明:本文为博主原创文章,爱转载的表明出处就好. https://blog.csdn.net/qq_36797743/article/details/81611312
题意
自己看
题解
感觉这个构造并不是很会想。。
考虑,我们随便枚举一个点
然后,我们把他可以直接到达的点全部删掉
剩下一个图
如果我们可以得到这个图的合法方案
然后看一下,如果剩下的图中,有一个有色点可以到达
,那么
和他所连向的点不染色即可
否则,我们把
染色肯定是合法的
于是得到一个做法
从1到n扫过去,如果这个点还在,就把他删掉,模拟上述过程
然后把删掉的点倒着做回来更新图即可
CODE:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<stack>
using namespace std;
const int N=1000005;
int n,m;
struct qq
{
int x,y,last;
}e[N];int num,last[N];
void init (int x,int y)
{
num++;
e[num].x=x;e[num].y=y;
e[num].last=last[x];
last[x]=num;
}
bool del[N];
bool ok[N];
stack<int> sta;
int ans[N];
int main()
{
memset(ok,true,sizeof(ok));
memset(del,false,sizeof(del));
num=0;memset(last,-1,sizeof(last));
scanf("%d%d",&n,&m);
for (int u=1;u<=m;u++)
{
int x,y;
scanf("%d%d",&x,&y);
init(x,y);
}
for (int u=1;u<=n;u++)
if (del[u]==false)
{
sta.push(u);
//printf("%d\n",u);
for (int i=last[u];i!=-1;i=e[i].last)
{
int y=e[i].y;
del[y]=true;
}
}
while (!sta.empty())
{
int x=sta.top();sta.pop();
if (ok[x]==true)
{
//printf("x:%d %d\n",x,ok[x]);
for (int u=last[x];u!=-1;u=e[u].last)
{
int y=e[u].y;
ok[y]=false;
//printf("y:%d %d\n",y,ok[y]);
}
ans[++ans[0]]=x;
}
}
printf("%d\n",ans[0]);
for (int u=1;u<=ans[0];u++)
printf("%d ",ans[u]);
return 0;
}