样例解释
1660. 社交距离 II - AcWing题库
D,F两头牛之间不可能存在传染,因为E牛没有被传染,因此可以确定:
F牛一定是最开始感染的牛之一。
D牛和E牛之间的距离四4,因为E牛没有被传染,所以可以确定: 感染半径R一定小于4。
A牛和B牛之间的距离是4,C牛和D牛之间的距离是2,因为B牛和C牛之间不可能存在感染(距离为4,R小于4),因此A,B和C,D肯定是独立的。
假设R是C到D的距离(2),那么A就不可能感染B(距离为3)。
假设R是A到B的距离(3),那么A既可以感染B,C也可以感染D。
所以可以确定:感染距离就是3。
最开始被感染的三头牛是 A C F 或 B D F或 A D F。
最开始被感染的牛的个数就是3
总结规律
如果当前牛是健康牛,那么最短感染距离R要么在其左边,要么在其右边(显而易见)。
我们就在其左边,右边去寻找答案(类似二分)
最后我们可以找出一个最短感染距离R。
解题思想
#include<bits/stdc++.h>
using namespace std;
const int M=1e5+10;
const int N=1010;
typedef pair<int,int>PII;
int vis[M];
PII a[N];
int n;
void bfs(int x,int R)
{
queue<int> q;
q.push(a[x].first); //存一下第一个感染的牛的位置
vis[x]=1; //标记为走过
while(!q.empty())
{
int t=q.front();
q.pop();
int left=t-R,right=t+R;
for(int i=0;i<n;i++)
{
if(!vis[i]&&a[i].first>left&&a[i].first<right) //如果没有越界并且没有被遍历过
{
q.push(a[i].first);
vis[i]=1; //标记为走过
}
}
}
}
int main()
{
cin.tie(nullptr)->sync_with_stdio(false);
cin>>n;
for(int i=0;i<n;i++)
{
int x,y;cin>>x>>y;
a[i]={x,y};
}
sort(a,a+n);
//求最小感染半径R
int R=0x3f3f3f3f;
for(int i=0;i<n;i++)
{
//如果当前牛没有被感染
if(a[i].second==0)
{
//如果左边的牛被感染,R就更新为当前牛到左边牛的距离
if(i-1>=0&&a[i-1].second==1) R=min(R,a[i].first-a[i-1].first);
//如果右边的牛被感染,R就更新为当前牛到右边牛的距离
if(i+1<n&&a[i+1].second==1) R=min(R,a[i+1].first-a[i].first);
}
}
int res=0;
for(int i=0;i<n;i++)
{
//如果当前牛是感染牛 并且 还没有被遍历过 ,那我们就从前往后推,看着头牛最多传染多少头牛
if(a[i].second&&!vis[i])
{
res++;
bfs(i,R);
}
}
cout<<res<<endl;
return 0;
}