加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

UVA 11930 F Rectangles

(2011-03-01 16:27:08)
标签:

uva

11930

f

rectangles

it

分类: 图论
题目描述:
给你一些长方形(告诉你四个点坐标),每个长方形只可选择其两条对角线中的一条。问你又没有可能存在一种选择方案,使选择的对角线都不相交。
解题报告:
赤裸的2-sat,如果不了解2-sat,请看:
http://blog.sina.com.cn/s/blog_64675f540100k2xj.html

利用到的就是判断线段相交,比如i长方形的1号对角线和j长方形的2号对角线相交,那么连接
i1->j1(表示如果i选1号,那么j只能选1号),构图方法依次类推。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define SIZE 2000 // 点的个数
#define esize 4000000 // 边的个数
int v[SIZE], cnt;
struct edge{int from, to, next;}e[esize];
void insert(int from, int to)
{
    e[cnt].from = from, e[cnt].to = to; e[cnt].next = v[from]; v[from] = cnt++;
}
int index2, dfn[SIZE], low[SIZE], instack[SIZE], sta[SIZE], top;
int belong[SIZE], cntnum, num[SIZE];
void tarjan(int id)
{
    dfn[id] = low[id] = ++index2;
    instack[id] = 1; sta[top++] = id;
    int tmp = v[id];
    while(tmp != -1)
    {
        if (!dfn[e[tmp].to])
        {
            tarjan(e[tmp].to);
            if (low[e[tmp].to] < low[id]) low[id] = low[e[tmp].to];
        }
        else if (instack[e[tmp].to] && dfn[e[tmp].to] < low[id])
            low[id] = dfn[e[tmp].to];
        tmp = e[tmp].next;
    }
    if (dfn[id] == low[id])
    {
        do
        {
            tmp = sta[--top]; instack[tmp] = 0;
            belong[tmp] = cntnum;
            num[cntnum]++;
        }while(tmp != id);
        cntnum++;
    }
}
bool solve(int n) // n是一半的人数 执行tarjan和topsort,完成标记
{
    index2 = cntnum = top = 0;
    memset(dfn, 0, sizeof(dfn));
    memset(num, 0, sizeof(num));
    for(int i = 0; i < 2 * n; i++)
        if (!dfn[i]) tarjan(i);
    for(int i = 0; i < n; i++)     //在缩点的图中标记互斥的缩点。(原来互斥,现在也互斥)
        if (belong[i] == belong[i + n]) return false;
    return true;
}
struct pint
{
    double x, y;
};
int EPS(double xx)
{
    if (xx <= 0.00001 && xx >= -0.00001) return 0;
    else if (xx > 0) return 1;
    else return -1;
}
double direction(pint p1, pint p2, pint p3)
{
    return (p3.x - p1.x) * (p2.y - p1.y) - (p2.x - p1.x) * (p3.y - p1.y);
}
bool online(pint p1, pint p2, pint p3)
{
    return (p3.x >= min(p1.x, p2.x) && p3.x <= max(p1.x, p2.x) && p3.y >= min(p1.y, p2.y) && p3.y <= max(p1.y, p2.y));
}
bool insect(pint p1, pint p2, pint p3, pint p4)
{
    double d1 = direction(p3, p4, p1);
    double d2 = direction(p3, p4, p2);
    double d3 = direction(p1, p2, p3);
    double d4 = direction(p1, p2, p4);
    if (EPS(d1) * EPS(d2) < 0 && EPS(d3) * EPS(d4) < 0) return true;
    else if (EPS(d1) == 0 && online(p3, p4, p1)) return true;
    else if (EPS(d2) == 0 && online(p3, p4, p2)) return true;
    else if (EPS(d3) == 0 && online(p1, p2, p3)) return true;
    else if (EPS(d4) == 0 && online(p1, p2, p4)) return true;
    return false;
}
int n;
pint jeo[1000][4];
bool cmp(pint a, pint b)
{
    if (a.y == b.y) return a.x < b.x;
    return a.y < b.y;
}
int main()
{
    while(scanf("%d", &n) && n)
    {
        memset(v, -1, sizeof(v)); cnt = 0;
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < 4; j++)
                scanf("%lf%lf", &jeo[i][j].x, &jeo[i][j].y);
            sort(jeo[i], jeo[i] + 4, cmp);
        }
        for(int i = 0; i < n; i++)
            for(int j = i + 1; j < n; j++)
                if (i != j)
                {
                    if (insect(jeo[i][0], jeo[i][3], jeo[j][0], jeo[j][3]))
                    {
                        insert(i, j + n);
                        insert(j, i + n);
                    }
                    if (insect(jeo[i][0], jeo[i][3], jeo[j][1], jeo[j][2]))
                    {
                        insert(i, j);
                        insert(j + n, i + n);
                    }
                    if (insect(jeo[i][1], jeo[i][2], jeo[j][0], jeo[j][3]))
                    {
                        insert(i + n, j + n);
                        insert(j, i);
                    }
                    if (insect(jeo[i][1], jeo[i][2], jeo[j][1], jeo[j][2]))
                    {
                        insert(i + n , j);
                        insert(j + n, i);
                    }
                }
        if (solve(n))
            printf("YES\n");
        else printf("NO\n");
    }
}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有