hdu2295 求最小半径使->最多k个点可以覆盖所有点 : 二分半径+DLX可重复覆盖模板
可重复覆盖与精准覆盖的区别在于remove和resume函数
本题为了优化可以在每次枚举要删点前做一次类似A*的估价函数,看是否可以炸完=
1 #include<stdio.h> 2 #include<math.h> 3 #include<string.h> 4 #include<algorithm> 5 #define eps 1e-8 6 using namespace std; 7 struct dian{ 8 double x,y; 9 }a[55],b[55]; 10 int k; 11 double dis(dian n1,dian n2) 12 { 13 return sqrt((n1.x-n2.x)*(n1.x-n2.x)+(n1.y-n2.y)*(n1.y-n2.y)); 14 } 15 struct DLX{ 16 int n,m,size,ansd,ans[55]; 17 int U[3005],D[3005],L[3005],R[3005]; 18 int Row[3005],Col[3005],H[55],S[55]; 19 void init(int _n,int _m){ 20 n=_n; m=_m; 21 for (int i=0;i<=m;i++){ 22 S[i]=0; 23 U[i]=D[i]=i; 24 L[i]=i-1; R[i]=i+1; 25 } 26 R[m]=0; L[0]=m; 27 size=m; 28 for (int i=1;i<=n;i++) H[i]=-1; 29 } 30 void link(int r,int c){ 31 S[c]++; 32 Col[++size]=c; Row[size]=r; 33 D[size]=D[c]; U[D[c]]=size; 34 U[size]=c; D[c]=size; 35 if (H[r]<0) H[r]=L[size]=R[size]=size; 36 else{ 37 R[size]=R[H[r]]; 38 L[R[H[r]]]=size; 39 L[size]=H[r]; 40 R[H[r]]=size; 41 } 42 } 43 void remove(int c){ 44 for (int i=D[c];i!=c;i=D[i]) 45 L[R[i]]=L[i],R[L[i]]=R[i]; 46 } 47 void resume(int c){ 48 for (int i=U[c];i!=c;i=U[i]) 49 L[R[i]]=R[L[i]]=i; 50 } 51 int v[3005]; 52 int f(){ 53 int tmp=0; 54 for (int c=R[0];c!=0;c=R[c]) v[c]=1; 55 for (int c=R[0];c!=0;c=R[c]) 56 if (v[c]){ 57 tmp++; v[c]=0; 58 for (int i=D[c];i!=c;i=D[i]) 59 for (int j=R[i];j!=i;j=R[j]) 60 v[Col[j]]=0; 61 } 62 return tmp; 63 } 64 int Dance(int d){ 65 if (d+f()>k) return 0; 66 if (R[0]==0) return d<=k; 67 int c=R[0]; 68 for (int i=R[0];i;i=R[i]) 69 if (S[i]<S[c]) c=i; 70 for (int i=D[c];i!=c;i=D[i]){ 71 remove(i); 72 for (int j=R[i];j!=i;j=R[j]) remove(j); 73 //该炸弹所覆盖的所有城市都remove 74 if (Dance(d+1)) return 1; 75 for (int j=L[i];j!=i;j=L[j]) resume(j); 76 resume(i); 77 } 78 return 0; 79 } 80 }G; 81 int main() 82 { 83 int T,n,m,i,j; 84 double l,r,mid; 85 scanf("%d",&T); 86 while (T--){ 87 scanf("%d%d%d",&n,&m,&k); 88 for (i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y); 89 for (i=1;i<=m;i++) scanf("%lf%lf",&b[i].x,&b[i].y); 90 l=0; r=1e8; 91 while (r-l>=eps){ 92 mid=(l+r)/2;//二分半径后重构 93 G.init(m,n); 94 for (i=1;i<=m;i++) 95 for (j=1;j<=n;j++) 96 if (dis(b[i],a[j])<mid-eps) G.link(i,j); 97 if (G.Dance(0)) r=mid; 98 else l=mid; 99 } 100 printf("%.6lf\n",l); 101 } 102 return 0; 103 }