zoukankan      html  css  js  c++  java
  • HDU

    博主的 BiBi 时间

    感觉自己天天 BiBi 好累。。。(这种事情不是可以让它停止了吗滑稽)

    Solution

    这是比较典型的 (mathtt{2-SAT}) 问题。

    我们可以做一个二分,枚举最小半径。然后连边就是如果两个点的距离小于 (2*r) 就连。

    重要的是这道题有个坑:可能有不连边的情况。这种情况肯定是可以的,但是如果贸然进入 (mathtt{dfs}),再修改一些奇奇怪怪的值,就会有大问题。(比如后面 (belong) 数组的比较)最好特判掉。

    Code

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    
    const double eps = 1e-5;
    const int N = 205;
    
    int n, len, head[N], Head[N], scc[N], tot, cnt, to[N * N * 4], nxt[N * N * 4], be[N], x[N], y[N];
    bool vis[N];
    
    int read() {
    	int x = 0, f = 1; char s;
    	while((s = getchar()) > '9' || s < '0') if(s == '-') f = -1;
    	while(s >= '0' && s <= '9') x = (x << 1) + (x << 3) + (s ^ 48), s = getchar();
    	return x * f;
    }
    
    void addEdge(const int u, const int v) {
    	to[++ cnt] = v, nxt[cnt] = head[u], head[u] = cnt;
    	to[++ cnt] = u, nxt[cnt] = Head[v], Head[v] = cnt;
    }
    
    void dfs1(const int u) {
        vis[u] = 1;
        for(int i = head[u]; i; i = nxt[i])
            if(! vis[to[i]]) dfs1(to[i]);
        scc[++ tot] = u;
    }
    
    void dfs2(const int u) {
        vis[u] = 1; be[u] = tot;
        for(int i = Head[u]; i; i = nxt[i])
            if(! vis[to[i]]) dfs2(to[i]);
    }
    
    bool check(const double goal) {
    	memset(head, 0, sizeof head); memset(Head, 0, sizeof Head); cnt = 0;
    	for(int i = 0; i < n; ++ i)
    		for(int j = i + 1; j < n; ++ j)
    			if(sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j])) < goal * 2)
    				addEdge(i, j ^ 1), addEdge(j, i ^ 1);
        if(! cnt) return 1;
    	memset(vis, 0, sizeof vis); tot = 0;
    	for(int i = 0; i < n; ++ i) if(! vis[i]) dfs1(i);
    	memset(vis, 0, sizeof vis); tot = 0;
    	for(int i = n - 1; ~i; -- i)
    		if(! vis[scc[i]]) ++ tot, dfs2(scc[i]);
    	for(int i = 0; i < n; ++ i) if(be[i] == be[i ^ 1]) return 0;
    	return 1;
    }
    
    int main() {
    	double l, r, mid, ans;
    	while(~ scanf("%d", &n)) {
    		len = -1;
    		for(int i = 1; i <= n; ++ i) x[++ len] = read(), y[len] = read(), x[++ len] = read(), y[len] = read();
    		n <<= 1;
    		l = 0; r = 20000;
    		while(r - l > eps) {
    			mid = (l + r) / 2;
    			if(check(mid)) l = mid, ans = mid;
    			else r = mid;
    		}
    		printf("%.2f
    ", mid);
    	}
    	return 0;
    }
    
  • 相关阅读:
    HTTP协议抓包分析
    cmd 中使用 tracert
    Ubuntu 搭建zabbix
    kerberos+ldap
    运行程序显示丢失“MSVCR100D.dll”
    熊猫烧香病毒样本分析
    Masm32sdk安装指南
    16位汇编实现三大基本排序
    逆向工程初步160个crackme-------3
    一个入门级CTF的Reverse
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/13158089.html
Copyright © 2011-2022 走看看