题目大意
一个有向图无自环图,找到一个点集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<cstdio>
#include<algorithm>
#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);
}
本文介绍一种针对有向无自环图的点集构造算法,目标是找到一个点集S,使得点集中任意两点间距离大于等于2,同时对于集合外的点,至少存在一个集合内的点与其距离小于等于2。文章给出了一个构造性的解决方案,并通过示例代码展示了具体的实现过程。

1285

被折叠的 条评论
为什么被折叠?



