CF85E Guard Towers(二分答案+二分图)

题意

已知 N 座塔的坐标,N≤5000
把它们分成两组,使得同组内的两座塔的曼哈顿距离最大值最小
在此前提下求出有多少种分组方案 mod 109+7

题解

二分答案 mid
曼哈顿距离 >mid 的点连边
判定是否构成二分图
方案数为 2^最终的二分图连通块数目
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 const int N=5110;
 9 const int mod=1000000007;
10 int dis[N][N],n,x[N],y[N],c[N],ans,num; 
11 long long ksm(long long a,long long x){
12     long long ans=1;
13     while(x){
14         if(x&1){
15             ans=(ans*a)%mod;
16         }
17         x>>=1;
18         a=(a*a)%mod;
19     }
20     return ans;
21 }
22 bool dfs(int u,int x,int col){
23     for(int i=1;i<=n;i++){
24         if(dis[u][i]>x){
25             if(c[i]!=-1){
26                 if(c[i]==col^1)continue;
27                 if(c[i]==col) return true;
28             }
29             c[i]=col^1;
30             if(dfs(i,x,col^1))return true;
31         }
32     }
33     return false;
34 }
35 bool check(int x){
36 //    cout<<x<<"jsdfhjsdf"<<endl;
37     memset(c,-1,sizeof(c));
38     for(int i=1;i<=n;i++){
39         if(c[i]==-1){
40             c[i]=1;
41             if(dfs(i,x,1))return false;
42         }
43     }
44 //    cout<<x<<endl;
45 //    for(int i=1;i<=n;i++){
46 //        cout<<c[i]<<" ";
47 //    }
48 //    cout<<endl;
49     return true;
50 }
51 void bfs(int u,int col){
52     queue<int> q;
53     c[u]=col;
54     q.push(u);
55     while(!q.empty()){
56         int u=q.front();
57         q.pop();
58         for(int i=1;i<=n;i++){
59             if(c[i])continue;
60             if(dis[i][u]>ans)c[i]=col,q.push(i);
61         }
62     } 
63 }
64 int main(){
65     scanf("%d",&n);
66     for(int i=1;i<=n;i++){
67         scanf("%d%d",&x[i],&y[i]);
68     }
69     for(int i=1;i<=n;i++)    
70         for(int j=1;j<=n;j++){
71             dis[i][j]=abs(x[i]-x[j])+abs(y[i]-y[j]);
72 //            cout<<i<<" "<<j<<" "<<dis[i][j]<<endl; 
73         } 
74     int l=0,r=10001;
75     while(l<=r){
76         int mid=(l+r)>>1;
77         if(check(mid)){
78             ans=mid;
79             r=mid-1;
80         }
81         else l=mid+1;
82     }
83     printf("%d\n",ans);
84     memset(c,0,sizeof(c));
85     for(int i=1;i<=n;i++){
86         if(c[i]==0){
87             bfs(i,++num);
88         }
89     }
90     printf("%lld",ksm(2,num));
91 }
View Code

 

posted @ 2018-07-29 17:05  Xu-daxia  阅读(369)  评论(0编辑  收藏  举报