P7639 [BalticOI 2006 Day 1] COUNTRIES
题意
在一个二维平面上有
定义城市
一个城市的性质有以下三种可能:
-
一个王国的首都。这个城市不受任何城市的威胁。
-
一个民主国家的首都。这个城市受到多个城市的威胁,且有多个城市对这个城市的威胁值与这个城市所受最大威胁值相等。
-
服从于另一个作为首都的城市。这个城市受到多个城市的威胁,且这些城市中有且仅有一个对它威胁值最大的城市
id ,那么这个城市将服从于城市id 或城市id 所服从的首都。
请给出每一个城市的性质。
思路
对于每一个城市,枚举所有城市,找到所有能对其产生威胁的城市。记录这个城市所受最大威胁值
-
当
cnt=0 时,表示这个城市不受任何城市威胁,这个城市为王国的首都。 -
当
cnt=1 时,表示这个城市服从于城市id (对它的威胁值为mx )。当出现这种情况时,可使用并查集维护城市之间的服从关系。 -
当
cnt\geq 2 时,表示这个城市同时受多个威胁值为mx 的城市威胁,这个城市为民主国家的首都。
时间复杂度为
代码实现
1. 城市信息存储
可以使用结构体存储。
struct node{
int x,y,s,fa,f;
}a[maxn];
其中,
2. 城市对其他城市的威胁值计算
计算城市
double dis(int i,int j){
return (double)((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
}
于是我们得到城市
t=(double)a[j].s/dis(i,j); // 城市 j 的兵力除以距离的平方
注意这里应该用 double 类型存储威胁值,因为它不一定是一个整数。
3. 城市性质的判断
当获得城市
由于威胁值用浮点数存储,会产生精度问题。我们需要加一个判断浮点数是否相等的函数。
bool check(double x,double y){
if(_abs(x-y)<=1e-10)return 1; // 若两个浮点数的误差小于一定值,则认为这两个浮点数是相等的
return 0;
}
在得到
int getfa(int x){
return (a[x].fa==x)?x:(a[x].fa=getfa(a[x].fa)); // 并查集
}
for(int i=1;i<=n;i++){
int id=0,cnt=0; // 产生最大威胁值的城市编号、产生最大威胁值的城市个数
double mx=0; // 城市 i 所受最大威胁值
for(int j=1;j<=n;j++){
if(i==j)continue;
double t=(double)a[j].s/dis(i,j); // 计算 j 对 i 的威胁值
if(t<(double)a[i].s||check(t,(double)a[i].s))continue; // 若 t < a[i].s 或 t == a[i].s ,跳过
if(t>mx&&!check(mx,t))mx=t,id=j,cnt=1; // 若 t > 当前城市 i 所受最大威胁值 mx ,则更新 mx 、 id 与 cnt
else if(check(t,mx))cnt++; // 若 t == mx ,产生最大威胁值的城市个数加一
}
if(!cnt)a[i].f=1; // 城市 i 为王国的首都
if(cnt>1)a[i].f=2; // 城市 i 为民主国家的首都
if(cnt==1)a[i].fa=getfa(id); // 城市 i 服从于城市 id
}
在此之后,还需要进行:
for(int i=1;i<=n;i++)getfa(i);
这样可以保证找到每个城市服从的首都。
完整代码
#include<bits/stdc++.h>
#define int long long
#define _abs(x) ((x)>0?(x):(-(x)))
#define maxn 1010
using namespace std;
int n;
struct node{
int x,y,s,fa,f;
}a[maxn];
inline int read(){
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')ret=ret*10+(ch&15),ch=getchar();
return ret*f;
}
double dis(int i,int j){
return (double)((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
}
bool check(double x,double y){
if(_abs(x-y)<=1e-10)return 1;
return 0;
}
int getfa(int x){
return (a[x].fa==x)?x:(a[x].fa=getfa(a[x].fa));
}
signed main(){
n=read();
for(int i=1;i<=n;i++)a[i].x=read(),a[i].y=read(),a[i].s=read(),a[i].fa=i;
for(int i=1;i<=n;i++){
int id=0,cnt=0;
double mx=0;
for(int j=1;j<=n;j++){
if(i==j)continue;
double t=(double)a[j].s/dis(i,j);
if(t<(double)a[i].s||check(t,(double)a[i].s))continue;
if(t>mx&&!check(mx,t))mx=t,id=j,cnt=1;
else if(check(t,mx))cnt++;
}
if(!cnt)a[i].f=1;
if(cnt>1)a[i].f=2;
if(cnt==1)a[i].fa=getfa(id);
}
for(int i=1;i<=n;i++)getfa(i);
for(int i=1;i<=n;i++){
if(a[i].fa==i)printf("%c\n",(a[i].f==1)?'K':'D');
else printf("%lld\n",a[i].fa);
}
return 0;
}