【题目大意】
给n对炸弹可以放置的位置(每个位置为一个二维平面上的点),每次放置炸弹是时只能选择这一对中的其中一个点,每个炸弹爆炸的范围半径都一样,控制爆炸的半径使得所有的爆炸范围都不相交(可以相切),求解这个最大半径。
【思路】
显然是二分答案!二分半径,2-SAT建图部分是最裸的。
【错误点】
注意一下精度啊,HDU根本不提供所谓的±0.01..
一开始写了printf("%.2f ",floor(ub*100)/100);
事实上写printf("%.2f ",ub);就好啦。
1 #include<bits/stdc++.h> 2 #define eps 1e-8 3 using namespace std; 4 const int MAXN=250; 5 const int INF=0x7fffffff; 6 int n; 7 int x[MAXN],y[MAXN]; 8 int dfn[MAXN],low[MAXN],col[MAXN],instack[MAXN],colcnt,cnt; 9 vector<int> E[MAXN]; 10 stack<int> S; 11 12 void addedge(int u,int v) 13 { 14 E[u].push_back(v); 15 } 16 17 double dist(int x1,int y1,int x2,int y2) 18 { 19 double ret=sqrt((double)(x1-x2)*(x1-x2)+(double)(y1-y2)*(y1-y2)); 20 //cout<<x1<<' '<<x2<<' '<<y1<<' '<<y2<<' '<<ret<<endl; 21 return ret; 22 } 23 24 void tarjan(int u) 25 { 26 dfn[u]=low[u]=++cnt; 27 instack[u]=1; 28 S.push(u); 29 for (int i=0;i<E[u].size();i++) 30 { 31 int v=E[u][i]; 32 if (!instack[v]) 33 { 34 tarjan(v); 35 low[u]=min(low[u],low[v]); 36 37 } 38 else if (instack[v]==1) low[u]=min(low[u],dfn[v]); 39 } 40 41 if (dfn[u]==low[u]) 42 { 43 colcnt++; 44 int x; 45 do 46 { 47 x=S.top(); 48 col[x]=colcnt; 49 instack[x]=2; 50 S.pop(); 51 }while (x!=u); 52 } 53 } 54 55 void build(double r) 56 { 57 for (int i=0;i<MAXN;i++) vector<int>().swap(E[i]); 58 for (int i=1;i<=n-1;i++) 59 for (int j=i+1;j<=n;j++) 60 { 61 if (dist(x[i],y[i],x[j],y[j])<2*r) addedge(i,j+n),addedge(j,i+n); 62 if (dist(x[i],y[i],x[j+n],y[j+n])<2*r) addedge(i,j),addedge(j+n,i+n); 63 if (dist(x[i+n],y[i+n],x[j],y[j])<2*r) addedge(i+n,j+n),addedge(j,i); 64 if (dist(x[i+n],y[i+n],x[j+n],y[j+n])<2*r) addedge(i+n,j),addedge(j+n,i); 65 } 66 } 67 68 void init() 69 { 70 for (int i=1;i<=n;i++) 71 { 72 scanf("%d%d",&x[i],&y[i]); 73 scanf("%d%d",&x[i+n],&y[i+n]); 74 } 75 } 76 77 void solve() 78 { 79 double lb=0,ub=INF; 80 while (ub-lb>eps) 81 { 82 double mid=(lb+ub)/2; 83 build(mid); 84 memset(instack,0,sizeof(instack)); 85 colcnt=cnt=0; 86 for (int i=1;i<=2*n;i++) if (!instack[i]) tarjan(i); 87 int flag=1; 88 for (int i=1;i<=n;i++) 89 if (col[i]==col[i+n]) 90 { 91 flag=0; 92 break; 93 } 94 if (flag) lb=mid; 95 else ub=mid; 96 } 97 printf("%.2f ",ub); 98 } 99 100 int main() 101 { 102 while (scanf("%d",&n)!=EOF) 103 { 104 init(); 105 solve(); 106 } 107 return 0; 108 }
[写随机数据上瘾了所以这次也附上]
1 #include<bits/stdc++.h> 2 3 int main() 4 { 5 freopen("test.out","w",stdout); 6 for (int i=1;i<=20;i++) 7 { 8 int n=rand()%98+2; 9 printf("%d ",n); 10 for (int j=1;j<=n;j++) 11 { 12 int x=rand()%2001-1000,y=rand()%2001-1000; 13 printf("%d %d ",x,y); 14 x=rand()%2001-1000,y=rand()%2001-1000; 15 printf("%d %d ",x,y); 16 } 17 } 18 return 0; 19 }