1. 程式人生 > >CF85E Guard Towers(二分答案+二分圖)

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

std pan span code continue scanf \n () 連通

題意

已知 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

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