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 }