zoj 3370(二分+二分图染色)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3912
思路:二分覆盖直径,然后判断是否有冲突(即距离小于等于直径的不能使用同一频率),这样可以用二分图染色的办法判断,看是否能将整个图都染上色。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cmath> 7 using namespace std; 8 #define MAXN 1444 9 #define inf 1<<30 10 #define eps 1e-9 11 12 struct Point{ 13 double x,y; 14 }p[MAXN]; 15 16 double map[MAXN][MAXN]; 17 int color[MAXN]; 18 int ans[MAXN]; 19 int n; 20 21 double Get_Dist(int i,int j) 22 { 23 double d1=(p[i].x-p[j].x)*(p[i].x-p[j].x); 24 double d2=(p[i].y-p[j].y)*(p[i].y-p[j].y); 25 return sqrt(d1+d2); 26 } 27 28 bool Judge(double limit) 29 { 30 memset(color,0,sizeof(color)); 31 queue<int>que; 32 for(int i=1;i<=n;i++){ 33 if(color[i]==0){ 34 color[i]=1; 35 que.push(i); 36 while(!que.empty()){ 37 int u=que.front(); 38 que.pop(); 39 for(int v=1;v<=n;v++){ 40 if(map[u][v]>limit-eps)continue; 41 if(color[u]==color[v])return false; 42 if(color[v]==0){ 43 color[v]=3-color[u]; 44 que.push(v); 45 } 46 } 47 } 48 } 49 } 50 for(int i=1;i<=n;i++)ans[i]=color[i]; 51 return true; 52 } 53 54 55 56 int main() 57 { 58 while(~scanf("%d",&n)){ 59 for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y); 60 for(int i=1;i<=n;i++) 61 for(int j=1;j<=n;j++) 62 map[i][j]=(i==j?inf:Get_Dist(i,j)); 63 double low=0,high=40000.0,mid; 64 while(high-low>eps){ 65 mid=(low+high)/2; 66 if(Judge(mid)){ 67 low=mid; 68 }else 69 high=mid; 70 } 71 printf("%.10f\n",mid/2); 72 for(int i=1;i<=n;i++){ 73 printf(i==n?"%d\n":"%d ",ans[i]); 74 } 75 } 76 return 0; 77 }