zoj 2318 Get Out! 计算几何spfa判负环

题意:给出n个圆心及半径,再给出一个特殊圆心及半径,问这个圆能不能逃出这n个圆的包围

 

首先先处理一下,将所有圆平移,使特殊圆在原点上,然后其他圆半径加上特殊圆的半径,这样特殊圆就可看成一个点而已,问题变为该点是否可以逃出实际上对于相交的两个圆,我们可以用他们圆心连线来代替它们。这样问题变为是否存在一个多边形,使得原点在这个多边行内部。

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;
#define LL long long
#define eps 1e-6
double pi=2*asin(1);

struct circle
{
    double x,y,r;
}p[310];
struct Node
{
    int v,nxt;
    double w;
}node[310*310];
int n,vis[310],f[310],g[310],alloc;
double d[310];
void add(int a,int b,double c)
{
    node[alloc].v=b;
    node[alloc].nxt=g[a];
    node[alloc].w=c;
    g[a]=alloc++;
}
double dist(int a,int b)
{
    return hypot(fabs(p[a].x-p[b].x),fabs(p[a].y-p[b].y));
}
bool spfa()
{
    queue<int>Q;
    for(int i=1;i<=n;i++)
    {
        Q.push(i);
        vis[i]=1;
        f[i]=0;
        d[i]=0;
    }
    while(!Q.empty())
    {
        int u=Q.front();Q.pop();
        vis[u]=0;
        for(int son=g[u];son!=-1;son=node[son].nxt)
        {
            int v=node[son].v;
            double w=node[son].w;
            if(d[v]>eps+d[u]+w)
            {
                d[v]=d[u]+w;
                if(!vis[v])
                {
                    f[v]++;
                    if(f[v]>=n) return false;
                    vis[v]=1;
                    Q.push(v);
                }
            }
        }
    }
    return true;
}
int main()
{
    int T,i,j;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++)
            scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].r);
        scanf("%lf%lf%lf",&p[0].x,&p[0].y,&p[0].r);
        for(i=1;i<=n;i++)
        {
            p[i].x-=p[0].x;
            p[i].y-=p[0].y;
            p[i].r+=p[0].r;
        }
        p[0].x=p[0].y=0;
        memset(g,-1,sizeof(g));
        alloc=0;
        for(i=1;i<=n;i++)
        {
            for(j=i+1;j<=n;j++)
            {
                if(p[i].r+p[j].r-eps<dist(i,j)) continue;
                double C=acos((p[i].x*p[j].x+p[i].y*p[j].y)/dist(0,i)/dist(0,j));
                bool flag=(p[i].x*p[j].y-p[j].x*p[i].y)>=0;
                add(i,j,flag?C:-C);
                add(j,i,!flag?C:-C);
            }
        }
        if(spfa()) printf("YES\n");
        else printf("NO\n");
        if(T) printf("\n");
    }
    return 0;
}

 

posted on 2016-02-26 21:50  13rj1115  阅读(253)  评论(0编辑  收藏  举报

导航