CF1949I Disks
题意
平面直角坐标系上有 \(n\pod {1\le n\le 1000}\) 个圆。任意两个圆没有相交关系。请问能否改变一些圆的半径,使得没有圆有相交关系,原来相切的圆现在仍然相切,且半径之和减小。
思路
这题评蓝?
因为半径改变大小任意,所以只有相切的圆才会相互影响,于是我们将相切的圆连边,再对每个连通块单独考虑。
这里给出一个重要的结论:两个圆若圆心不变且相切,则半径之和等于圆心距。于是对于相切的两个圆,若一个圆半径减小,另一个圆半径一定增大,且增减量相等。
于是我们可以将圆分为两类:半径减小的圆和半径增大的圆,也就是构造二分图。对于半径减小的圆,跟它有连边的圆一定为半径增大的圆,反之亦然。当出现矛盾时,则不能改变半径大小。
以上过程即为二分图判定过程。
构造出二分图后,任意一类点都可以成为半径减小的圆,我们考虑让点数更多的一类点成为半径减小的圆,这样可以使得减少量大于增加量。当点数相等时,该连通块增减量相等,也不能改变半径之和的大小。
于是我们将所有相切的圆连边,并对每个连通块判定二分图,若某个连通块为二分图且两类点数不相等,答案即为 YES
,否则为 NO
。
注意开 long long
。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,col[1005],cc[2],ans;
struct node{int x,y,d;
}a[1005];
vector<int> t[1005];
bool is_cut(node x,node y){return (x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y)==(x.d+y.d)*(x.d+y.d);
}
void dfs(int x,int c){col[x]=c,cc[c]++;for(int v:t[x]){if(col[v]==-1)dfs(v,c^1);else if(col[v]!=(c^1))ans=0;}
}
signed main() {ios::sync_with_stdio(false);cin.tie(nullptr),cout.tie(nullptr);memset(col,-1,sizeof(col));cin>>n;for(int i=1;i<=n;i++)cin>>a[i].x>>a[i].y>>a[i].d;for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++){if(is_cut(a[i],a[j]))t[i].push_back(j),t[j].push_back(i);}}for(int i=1;i<=n;i++){if(col[i]==-1){cc[0]=cc[1]=0;ans=1;dfs(i,0);if(ans&&cc[0]!=cc[1]){cout<<"YES"<<endl;return 0;}}}cout<<"NO"<<endl;return 0;
}