只需要每次找到一个没有被覆盖的点选掉就可以了。考虑新方案和原方案,最坏情况是没有选到原方案选的点,而是选到了它旁边的点。但是即使这样,新点覆盖的范围也是只多不少。
注意此题没有spj,需要从小到大枚举,也就是输出字典序最小的解。
#include<cstdio>
#include<algorithm>
const int maxn=2000010;
int fir[maxn],ne[maxn],to[maxn],tag[maxn],vis[maxn],ans[maxn],n,m,k,num;
void add(int num,int u,int v)
{ne[num]=fir[u];fir[u]=num;to[num]=v;
}
int main()
{int u,v;scanf("%d%d%d",&n,&m,&k);for (int i=1;i<=m;i++){scanf("%d%d",&u,&v);add(i<<1,u,v);add(i<<1|1,v,u);}for (int i=n;i;i--)if (!vis[i]){vis[i]=1;ans[++num]=i;for (int j=fir[i];j;j=ne[j]){vis[to[j]]=1;for (int k=fir[to[j]];k;k=ne[k]) vis[to[k]]=1;}}printf("%d\n",num);for (int i=1;i<=num;i++) printf("%d ",ans[i]);
}