【ACdream】1215 Get Out! 负环判断

来源:互联网 发布:简单网络管理协议组成 编辑:程序博客网 时间:2024/05/16 15:10

传送门:【ACdream】1215 Get Out!


题目分析:首先将所有点平移,使得人在原点位置。然后所有圆的半径加上人的半径(人变成了点),然后对每两个圆之间判断,如果这两个圆有两个交点,则对这两个圆建边。那么题目就转化成了判断人是否在多边形内。如果我们将每条边变成两条有向边,边的权值为有向弧度。那么如果点在多边形内,则必定存在多边形边权和等于2pi或-2pi,也就是说存在负环。如果点不在多边形内,则该多边形权值和等于0。那么我们只要用spfa判断是否存在负环即可。

注意精度问题= =。。因为这个导致我一开始一直TLE。。


代码如下:


#include <cmath>#include <cstdio>#include <cstring>#include <algorithm>using namespace std ;#define rep( i , a , b ) for ( int i = ( a ) ; i <  ( b ) ; ++ i )#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )#define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 305 ;const int MAXE = 100005 ;const double INF = 1e15 ;const double eps = 1e-8 ;const double pi = acos ( -1.0 ) ;struct Edge {int v , n ;double c ;Edge () {}Edge ( int v , double c , int n ) : v ( v ) , c ( c ) , n ( n ) {}} ;struct Point {double x , y ;Point () {}Point ( double x , double y ) : x ( x ) , y ( y ) {}Point operator - ( const Point& p ) const {return Point ( x - p.x , y - p.y ) ;}} ;struct Circle {Point p ;double r ;void input () {scanf ( "%lf%lf%lf" , &p.x , &p.y , &r ) ;}} ;Edge E[MAXE] ;Circle C[MAXN] ;int H[MAXN] , cntE ;double d[MAXN] ;int vis[MAXN] , Time ;int Q[MAXN] , head , tail ;int use[MAXN] ;int n ;void clear () {cntE = 0 ;clr ( use , 0 ) ;clr ( H , -1 ) ;}void addedge ( int u , int v , double c ) {E[cntE] = Edge ( v , c , H[u] ) ;H[u] = cntE ++ ;}double dist ( const Point& p ) {return sqrt ( p.x * p.x + p.y * p.y ) ;}int dcmp ( double x ) {return ( x > eps ) - ( x < -eps ) ;}int spfa ( int s ) {For ( i , 1 , n ) d[i] = INF ;//clr ( use , 0 ) ;++ Time ;head = tail = 0 ;Q[tail ++] = s ;d[s] = 0 ;use[s] = 1 ;while ( head != tail ) {int u = Q[head ++] ;if ( head == MAXN ) head = 0 ;vis[u] = Time - 1 ;for ( int i = H[u] ; ~i ; i = E[i].n ) {int v = E[i].v ;if ( dcmp ( d[v] - d[u] - E[i].c ) > 0 ) {d[v] = d[u] + E[i].c ;if ( Time != vis[v] ) {vis[v] = Time ;use[v] ++ ;if ( use[v] == n + 5 ) return 1 ;Q[tail ++] = v ;if ( tail == MAXN ) tail = 0 ;}}}}return 0 ;}void solve () {Circle a ;clear () ;For ( i , 1 , n ) C[i].input () ;a.input () ;For ( i , 1 , n ) {C[i].p = C[i].p - a.p ;C[i].r += a.r ;}For ( i , 1 , n ) {For ( j , i + 1 , n ) {if ( dcmp ( dist ( C[i].p - C[j].p ) - ( C[i].r + C[j].r ) ) < 0 ) {double ang1 = atan2 ( C[i].p.y , C[i].p.x ) ;double ang2 = atan2 ( C[j].p.y , C[j].p.x ) ;if ( dcmp ( ang1 ) < 0 ) ang1 = 2 * pi + ang1 ;if ( dcmp ( ang2 ) < 0 ) ang2 = 2 * pi + ang2 ;double ang = ang1 - ang2 ;if ( dcmp ( ang - pi ) > 0 ) ang = ang - 2 * pi ;if ( dcmp ( ang + pi ) < 0 ) ang = 2 * pi + ang ;addedge ( i , j , ang ) ;addedge ( j , i , -ang ) ;}}}For ( i , 1 , n ) if ( spfa ( i ) ) {printf ( "NO\n" ) ;return ;}printf ( "YES\n" ) ;}int main () {clr ( vis , 0 ) ;Time = 0 ;while ( ~scanf ( "%d" , &n ) ) solve () ;return 0 ;}


0 0
原创粉丝点击