http://acm.hdu.edu.cn/showproblem.php?pid=3622
又是各种逗。。
2-SAT是一种二元约束,每个点可以置于两种状态,但只能处于一种状态,然后图是否有解就是2-SAT啦。
看白书吧。
这个图的边的概念一定要弄懂!以下的x'表示x的另一个点
边(x, y)表示取了x就一定取y,x是前提条件!
对于约束(x, y),取x但不取y,那么显然连边(x, y'), (y, x'),这个意思一定要懂,就是说取了x就取y的另一个,可以唯一确定;那么反之取了y就一定取x的另一个(这里一定不是(x', y),因为x'是由y决定而不是y由x'决定)=
upd:我不知道前边在说什么,,,其实很简单的,对于两个状态x和y,假设我们要满足(x=1 或 y=0),那么显然当x=0时要满足这个性质,那么y只能=0。反之亦然。所以就是连边x0->y0, y1->x1。这题也是同理,对于状态x和y,如果x1和y1不能撮合,那么就连边x0->y1, y0->x1,这是因为我们必须要满足取一个,即(x=1 或 y=1),至少取一个,那么当x=0时,就只能连y1,(当然不考虑x0和y1冲突,因为我们分两次建图。。。如果到最后冲突,说明无解)
sigh..
这篇博文讲得十分详细orz http://www.cnblogs.com/kuangbin/archive/2012/10/05/2712429.html
白书上写的是dfs求,还有一种是tarjan缩点求。。
我暂时写白书的。。
本题只要二分半径然后连边即可。
#include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include <queue> using namespace std; #define rep(i, n) for(int i=0; i<(n); ++i) #define for1(i,a,n) for(int i=(a);i<=(n);++i) #define for2(i,a,n) for(int i=(a);i<(n);++i) #define for3(i,a,n) for(int i=(a);i>=(n);--i) #define for4(i,a,n) for(int i=(a);i>(n);--i) #define CC(i,a) memset(i,a,sizeof(i)) #define read(a) a=getint() #define print(a) printf("%d", a) #define dbg(x) cout << (#x) << " = " << (x) << endl #define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; } #define printarr1(a, b) for1(_, 1, b) cout << a[_] << '\t'; cout << endl inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; } inline const int max(const int &a, const int &b) { return a>b?a:b; } inline const int min(const int &a, const int &b) { return a<b?a:b; } const int N=215; const double eps=1e-4; int n, nn, x[N], y[N], vis[N], s[N], ihead[N], cnt, top; struct ED { int to, next; }e[(N*N)<<1]; void add(int u, int v) { e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v; } bool dfs(int u) { if(vis[u]) return true; if(vis[u^1]) return false; vis[u]=true; s[++top]=u; for(int i=ihead[u]; i; i=e[i].next) if(!dfs(e[i].to)) return false; return true; } bool check(double r) { CC(ihead, 0); cnt=0; CC(vis, 0); double dis=(r*r)*4; for1(i, 2, nn) { int t; if(i&1) t=i+1; else t=i+2; for1(j, t, nn) { double x1=x[i], y1=y[i], x2=x[j], y2=y[j]; double rg=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2); if(rg<dis) add(i, j^1), add(j, i^1); } } for(int i=2; i<nn; i+=2) if(!vis[i] && !vis[i+1]) { top=0; if(!dfs(i)) { while(top) vis[s[top--]]=0; if(!dfs(i+1)) return false; } } return true; } int main() { while(~scanf("%d", &n)) { for1(i, 1, n) rep(j, 2) read(x[(i<<1)+j]), read(y[(i<<1)+j]); nn=(n<<1)+1; double l=0, r=50000; while(r-l>eps) { double m=(l+r)/2; if(check(m)) l=m; else r=m; } printf("%.2lf\n", l); } return 0; }