题目大意:有一个n个点m条边的图,每条边距离是1,已知用k个攻击距离为1的塔可以打到整个地图,让构造一个方案使得用小于等于k个攻击距离为2的塔打到整个地图
说是有spj,但是实际上没有,不过没有关系,因为这题每次挑一个没被覆盖的放就可以了,总个数一定小于等于k
怎么证明呢?
假设当前选择了一个还没被覆盖的点,那就在这里放一个攻击距离为2的塔
而在原方案中能覆盖这个点的所有塔的攻击范围的并集一定小于等于这个攻击距离为2的塔的攻击范围(这个很好证)
所以这样一定能在k个塔以内覆盖全部
没有spj,那就只能贪心的先放小的了
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define N 1000010
using namespace std;
int to[N<<1],nxt[N<<1],pre[N],cnt;
void ae(int ff,int tt)
{
cnt++;
to[cnt]=tt;
nxt[cnt]=pre[ff];
pre[ff]=cnt;
}
bool used[N],used2[N];
void upd2(int x)
{
used[x]=true;
int i,j;
for(i=pre[x];i;i=nxt[i])
{
j=to[i];
used[j]=true;
}
}
void upd(int x)
{
used[x]=true;
used2[x]=true;
int i,j;
for(i=pre[x];i;i=nxt[i])
{
j=to[i];
if(used2[j]) continue;
used2[j]=true;
upd2(j);
}
}
int chs[N];
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
int i,j,x,y;
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
ae(x,y);ae(y,x);
}
int tot=0;
for(i=1;i<=n;i++)
if(!used[i])
{
tot++;
chs[tot]=i;
upd(i);
}
printf("%d\n",tot);
for(i=1;i<tot;i++)
printf("%d ",chs[i]);
printf("%d",chs[tot]);
}