大意:给定X、Y定圆,一次只能选一个,圆之间不能互相冲突,问:最大的满足条件的半径是多少?
思路:二分半径,2-SAT判断是否满足条件。
#include <iostream> #include <cstdlib> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <vector> #include <queue> #include <algorithm> #include <map> using namespace std; const int maxn = 210; const int maxm = 210*210*2; struct Edge { int v, w; int next; int id; }edge[maxm]; int first[maxn], stack[maxn], ins[maxn], dfn[maxn], low[maxn]; int belong[maxn]; int n, m; int cnt; int scnt, top, tot; void init() { cnt = 0; scnt = top = tot = 0; memset(first, -1, sizeof(first)); memset(dfn, 0, sizeof(dfn)); memset(ins, 0, sizeof(ins)); memset(low, 0, sizeof(low)); } void read_graph(int u, int v) { edge[cnt].v = v; edge[cnt].next = first[u], first[u] = cnt++; } void dfs(int u) { int v; low[u] = dfn[u] = ++tot; stack[top++] = u; ins[u] = 1; for(int e = first[u]; e != -1; e = edge[e].next) { v = edge[e].v; if(!dfn[v]) { dfs(v); low[u] = min(low[u], low[v]); } else if(ins[v]) { low[u] = min(low[u], dfn[v]); } } if(low[u] == dfn[u]) { scnt++; do { v = stack[--top]; belong[v] = scnt; ins[v] = 0; } while(u != v); } } void Tarjan() { for(int v = 0; v < 2*n; v++) if(!dfn[v]) dfs(v); } void readint(int &x) { char c; while(!isdigit(c)) c = getchar(); x = 0; while(isdigit(c)) { x = x*10 + c-'0'; c = getchar(); } } void writeint(int x) { if(x > 9) writeint(x/10); putchar(x%10+'0'); } struct Point { double x, y; Point(double x=0, double y=0): x(x), y(y) {} }; Point P[maxn]; double L, R; double sqr(double x) { return x*x ;} double Dist(Point a, Point b) { return sqrt(sqr(a.x-b.x) + sqr(a.y-b.y)); } double dist[maxn][maxn]; const double INF = 1e60; const double eps = 1e-6; void read_case() { double x1, y1, x2, y2; L = INF, R = -INF; for(int i = 0; i < n; i++) { scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); P[i] = Point(x1, y1), P[i+n] = Point(x2, y2); } for(int i = 0; i < 2*n; i++) for(int j = i+1; j < 2*n; j++) { dist[i][j] = dist[j][i] = Dist(P[i], P[j]); L = min(L, dist[i][j]), R = max(R, dist[i][j]); } } int check() { for(int i = 0; i < n; i++) if(belong[i] == belong[n+i]) return 0; return 1; } void build(double mid) { init(); for(int i = 0; i < 2*n; i++) { for(int j = 0; j < 2*n; j++) if(i != j) { if(dist[i][j] < 2*mid) //圆心距小于半径*2 { if(i < n && j < n) { read_graph(i, j+n); read_graph(j, i+n); } else if(i < n && j >= n) { read_graph(i, j-n); read_graph(j, i+n); } else if(i >= n && j < n) { read_graph(i, j+n); read_graph(j, i-n); } else { read_graph(i, j-n); read_graph(j, i-n); } } } } Tarjan(); } double BSearch() { double ans = 0; L /= 2, R /= 2; while(R-L >= eps) { double mid = L+(R-L)/2; build(mid); if(check()) L = mid; else R = mid; } return L; } void solve() { read_case(); double ans = BSearch(); printf("%.2lf\n", ans); } int main() { while(~scanf("%d", &n)) { solve(); } return 0; }