[CF1019C]Sergey's problem

题目大意

一个有向图无自环图,找到一个点集S满足:
点集内任意两个不同的点x和y,满足d(x,y)>=2。
对于任意一个不在点集内的点y,存在一个点集内的点x,满足d(x,y)<=2。

构造

对于任意图都存在解,构造性解法可以证明这点。
找到任意一点w,将w以及w的出边指向的点都删去,对剩余的图找到一个解S‘’。
如果存在一个u->w,且u在S’内,我们直接令S=S’,显然正确。
否则我们令S=S’ or {w},显然也正确。

#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=1000000+10;
int h[maxn],go[maxn*2],nxt[maxn*2];
bool bz[maxn],pd[maxn];
int i,j,k,l,t,n,m,now,tot;
int read(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9'){
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
void add(int x,int y){
    go[++tot]=y;
    nxt[tot]=h[x];
    h[x]=tot;
}
void solve(){
    while (now<=n&&bz[now]) now++;
    if (now>n) return;
    int x=now;
    bz[x]=1;
    int t=h[x];
    while (t){
        if (t%2) bz[go[t]]=1;
        t=nxt[t];
    }
    solve();
    t=h[x];
    while (t){
        if (t%2==0) pd[x]|=pd[go[t]];
        t=nxt[t];
    }
    pd[x]^=1;
}
int main(){
    n=read();m=read();
    fo(i,1,m){
        j=read();k=read();
        add(j,k);add(k,j);
    }
    now=1;
    solve();
    t=0;
    fo(i,1,n) t+=pd[i];
    printf("%d\n",t);
    fo(i,1,n)
        if (pd[i]) printf("%d ",i);
}

你可能感兴趣的:(构造)