[zjoi2008]Risk

原来觉得写得太丑,于是删了,但现在又不会恢复,于是又发了一遍。。。
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cctype>
#include <map>
#include <set>
#include <string>
#include <queue>
#include <algorithm>
#include <fstream>
#include <iostream>
using namespace std;
 
#ifdef WIN32
#define fmt64 "%I64d"
#else
#define fmt64 "%lld"
#endif
#define PI M_PI
#define oo 0x13131313
#define PB push_back
#define PO pop_back
#define MP make_pair
#define fst first
#define snd second
#define iter iterator
#define pque priority_queue
#define cstr(a) (a).c_str()
 
#define FOR(i, j, k) for (i = (j); i <= (k); ++i)
#define ROF(i, j, k) for (i = (j); i >= (k); --i)
#define FER(e, d, u) for (e = d[u]; e; e = e->n)
#define FRE(i, a) for (i = (a).begin(); i != (a).end(); ++i)
 
typedef unsigned int uint;
typedef long long int64;
typedef unsigned long long uint64;
typedef long double real;
 
template<class T> inline T sqr(const T &a) {return a * a;}
template<class T> inline bool minfy(T &a, const T &b) {return b < a ? a = b, 1 : 0;}
template<class T> inline bool maxfy(T &a, const T &b) {return b > a ? a = b, 1 : 0;}
 
#define eps 1e-6
#define maxn 1205
#define maxm 5005
#define dual(e) (adjs + (((e) - adjs) ^ 1))
 
struct point {double x, y;};
struct seg {point x, y;};
double agl(point x) {return atan2(x.y, x.x);}
double len(point x) {return sqrt(sqr(x.x) + sqr(x.y));}
point operator -(point a) {return (point){-a.x, -a.y};}
point operator +(point a, point b) {return (point){a.x + b.x, a.y + b.y};}
point operator -(point a, point b) {return (point){a.x - b.x, a.y - b.y};}
double operator *(point a, point b) {return a.x * b.y - a.y * b.x;}
double operator /(point a, point b) {return a.x * b.x + a.y * b.y;}
 
int sig(double x)
{
    return x < -eps ? -1 : x > eps;
}
 
int aglcmp(double a, double b)
{
    return sig(a * b) >= 0 ? sig(a - b) :
        (a > 0 && b < 0 ? (a - b < PI ? 1 : -1) : (b - a > PI ? 1 : -1));
}
 
int n, m, tot, total, start, c[maxm], fa[maxn], deg[maxn], chd[maxn], fat[maxn];
point a[maxn], b[maxm];
vector<seg> poly[maxn];
vector<int> neib[maxn], ch[maxn], in[maxn];
bool hehe[maxn], out[maxn], lnk[maxn][maxn];
 
struct hash {point x; int t; hash *n;};
hash hashs[maxm * 2], *hadj = hashs, *list[maxm];
 
int gethash(point x)
{
    hash *e;
    uint k = (uint(x.x) * 13u + uint(x.y) * 1313u) % maxm;
    FER (e, list, k) if (e->x.x == x.x && e->x.y == x.y) return e->t;
    *(++hadj) = (hash) {x, ++tot, list[k]}, list[k] = hadj;
    return b[tot] = x, c[tot] = tot;
}
 
struct adjc {int s, t; adjc *n; bool vst; int f;};
adjc adjs[maxm * 2], *adj = adjs + 1, *edge[maxm];
 
void link(int x, int y)
{
    *(++adj) = (adjc) {x, y, edge[x]}, edge[x] = adj;
    *(++adj) = (adjc) {y, x, edge[y]}, edge[y] = adj;
}
 
bool bigger(int x, int y)
{
    return b[x].y > b[y].y || (!sig(b[x].y - b[y].y) && b[x].x < b[y].x);
}
 
bool lefter(double a, double b, double c)
{
    if (aglcmp(b, c) > 0) return aglcmp(a, c) > 0 && aglcmp(a, b) > 0;
    return aglcmp(a, c) > 0 || aglcmp(a, b) > 0;
}
 
void dfs(adjc *fr)
{
    adjc *e, *d = 0, *du = dual(fr);
    fr->vst = 1, fr->f = total;
    poly[total].PB((seg) {b[fr->s], b[fr->t]});
    if (du->f && !lnk[total][du->f]) {
        lnk[total][du->f] = lnk[du->f][total] = 1;
        neib[du->f].PB(total), neib[total].PB(du->f);
        if (hehe[du->f]) out[total] = 1;
    }
    if (fr->t == start) return;
    point x = b[fr->t];
    double c = agl(b[fr->t] - b[fr->s]);
    FER (e, edge, fr->t) if (e != du && !e->vst)
        if (!d || lefter(agl(b[e->t] - x), agl(b[d->t] - x), c)) d = e;
    dfs(d);
}
 
double cross(point x, seg s)
{
    if (s.x.y < s.y.y) swap(s.x, s.y);
    if (s.x.y < x.y + eps || s.y.y > x.y - eps) return -1;
    double d1 = abs(s.x.y - x.y), d2 = abs(s.y.y - x.y);
    double xx = s.x.x + (s.y.x - s.x.x) * d1 / (d1 + d2);
    return xx < x.x - eps ? x.x - xx : -1;
}
 
double surround(point x, vector<seg> &a)
{
    int tot = 0;
    double k, res = oo;
    vector<seg>::iter it, jt;
    FRE (it, a)
        if ((k = cross(x, *it)) != -1)
            ++tot, minfy(res, k);
        else if (!sig(x.y - it->x.y) && it->x.x < x.x + eps) {
            double s, t = it->y.y;
            if (it == a.begin()) s = a.back().x.y;
            else jt = it, --jt, s = jt->x.y;
            if (sig((s - x.y) * (t - x.y)) <= 0)
                ++tot, minfy(res, x.x - it->x.x);
        }
    return tot & 1 ? res : -1;
}
 
int q[maxn], *h, *t, ll[maxn], rr[maxn];
 
void show(vector<seg> &p)
{
    vector<seg>::iter i; cerr << endl;
    FRE (i, p) fprintf(stderr, "[[%.3lf, %.3lf], [%.3lf, %.3lf]]\n", i->x.x, i->x.y, i->y.x, i->y.y);
}
 
bool okay(vector<seg> &p)
{
    seg a = p.front(), b = p.back();
    double x = agl(a.y - a.x), y = agl(b.y - b.x);
    return aglcmp(x, y) < 0 ? p.clear(), 0 : 1;
}
 
void show(vector<int> &p)
{
    vector<int>::iter it;
    cerr << endl;
    FRE (it, p) cerr << *it << " ";
    cerr << endl;
}
 
int main()
{
    int i, j, l;
    cin >> n >> m;
    FOR (i, 1, n) scanf("%lf%lf", &a[i].x, &a[i].y);
    FOR (i, 1, m) {
        point x, y; int u, v;
        scanf("%lf%lf%lf%lf", &x.x, &x.y, &y.x, &y.y);
        u = gethash(x), v = gethash(y), link(u, v);
    }
    sort(c + 1, c + tot + 1, bigger);
    FOR (j, 1, tot)
        for (i = c[j]; ; ) {
            adjc *e, *d = 0; double k;
            FER (e, edge, i) if (!e->vst) /* not deleted */
                if ((k = agl(b[e->t] - b[i])) < -eps) /* the highest point */
                    if (!d || k < agl(b[d->t] - b[i])) d = e; /* the leftest edge */
            if (d) {
                ++total, start = d->s, dfs(d);
                if (!okay(poly[total])) {
                    hehe[total] = 1;
                    vector<int>::iter it;
                    FRE (it, neib[total]) out[*it] = 1;
                }
            } else break; /* no find */
        }
    FOR (i, 1, total - 2) if (!hehe[i])
        FOR (j, i + 1, total - 1) if (!hehe[j])
            FOR (l, j + 1, total) if (!hehe[l]) {
                if (lnk[i][j] && lnk[j][l]) lnk[i][l] = lnk[l][i] = 1;
                else if (lnk[i][j] && lnk[i][l]) lnk[j][l] = lnk[l][j] = 1;
                else if (lnk[i][l] && lnk[j][l]) lnk[i][j] = lnk[j][i] = 1;
            }
    FOR (i, 1, total) if (!hehe[i]) {
        int father = 0;
        point x = poly[i][0].x;
        double k, dist = oo;
        FOR (j, 1, total) if (i != j && !hehe[j] && !lnk[i][j]/* vital */)
            if (k = surround(x, poly[j]), k != -1 && minfy(dist, k))
                father = j;
        if (father) {
            ch[father].PB(i), fa[i] = father, ++deg[father];
            if (out[i]) in[father].PB(i);
        }
    }
    FOR (i, 1, n) ll[i] = i - 1, rr[i] = i + 1;
    rr[0] = 1, rr[n] = 0;
    h = q + 1, t = q;
    FOR (i, 1, total) if (!hehe[i] && !deg[i]) *(++t) = i;
    for (; h <= t; ++h) {
        if (fa[*h] && !--deg[fa[*h]]) *(++t) = fa[*h];
        int child = 0;
        double k, dist = oo;
        for (i = rr[0]; i; i = rr[i])
            if ((k = surround(a[i], poly[*h])) != -1)
                if (minfy(dist, k)) child = i;
        if (child) {
            chd[*h] = child, fat[child] = *h;
            ll[rr[child]] = ll[child], rr[ll[child]] = rr[child];
        }
    }
    FOR (i, 1, n) {
        j = 0, l = fat[i];
        vector<int>::iter it;
        FRE (it, neib[l]) if (!hehe[*it]) q[++j] = chd[*it]; /* neighbours */
        if (out[l] && fa[l]) q[++j] = chd[fa[l]]; /* father(forgotten) */ /* out!!!!!! */
        FRE (it, in[l]) q[++j] = chd[*it]; /* near sons(forgotten) */
        printf("%d", j);
        sort(q + 1, q + j + 1);
        FOR (l, 1, j) printf(" %d", q[l]);
        puts("");
    }
 
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值