zoukankan      html  css  js  c++  java
  • bzoj 1027 floyd求有向图最小环

    结合得好巧妙。。。。

    化简后的问题是:

    给你两个点集A,B,求B的一个子集BB,使得BB的凸包包含A的凸包,求BB的最小大小。

    先特判答案为1,2的情况,答案为3的情况,我们先构造一个有向图:

    对于B集合中的两个点u,v,如果 所有A集合的点都在u->v的左侧,那么就连一条u->v的边。

    于是我们可以证明一个包含A的凸包和我们连出来的有向图中的环一一对应(不考虑点数小于等于2的情况)。

    于是现在我们的问题就是求最小的一个环,用floyd搞,最后统计min(f[i][i])。

      1 /**************************************************************
      2     Problem: 1027
      3     User: idy002
      4     Language: C++
      5     Result: Accepted
      6     Time:1308 ms
      7     Memory:2008 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <cmath>
     12 #include <cstring>
     13 #include <algorithm>
     14 #define line(a,b) ((b)-(a))
     15 #define eps 1e-8
     16 #define oo 0x3f3f3f3f
     17 #define N 550
     18 using namespace std;
     19  
     20 int sg( double x ) { return (x>-eps)-(x<eps); }
     21 struct Vector {
     22     double x, y;
     23     Vector(){}
     24     Vector( double x, double y ):x(x),y(y){}
     25     Vector operator-( const Vector &b ) const { return Vector(x-b.x,y-b.y); }
     26     double operator^( const Vector &b ) const { return x*b.y-y*b.x; }
     27     double operator&( const Vector &b ) const { return x*b.x+y*b.y; }
     28     double len() { return sqrt(x*x+y*y); }
     29     bool operator<( const Vector &b ) const {
     30         return sg(x-b.x)<0 || (sg(x-b.x)==0 && sg(y-b.y)<0);
     31     }
     32     bool operator==( const Vector &b ) const {
     33         return sg(x-b.x)==0 && sg(y-b.y)==0;
     34     }
     35 };
     36 typedef Vector Point;
     37  
     38 int n, m;
     39 Point aa[N], bb[N];
     40 int dis[N][N];
     41  
     42 bool onleft( const Point &a, const Point &b, const Point &c ) {
     43     return sg(line(a,b)^line(a,c))>=0;
     44 }
     45 bool onseg( const Point &a, const Point &b, const Point &c ) {
     46     return sg(line(a,b)^line(a,c))==0 && sg(line(c,a)&line(c,b))<0;
     47 }
     48 bool case1() {
     49     if( m==1 ) {
     50         for( int i=1; i<=n; i++ )
     51             if( aa[i]==bb[1] ) 
     52                 return true;
     53     }
     54     return false;
     55 }
     56 bool case2() {
     57     bool ok = true;
     58     for( int i=1; i<=m && ok; i++ )
     59         for( int j=i+1; j<=m && ok; j++ )
     60             for( int k=j+1; k<=m && ok; k++ )
     61                 if( sg((bb[i]-bb[j])^(bb[k]-bb[j])) ) 
     62                     ok =false;
     63     if( ok ) {
     64         int ii=1, jj=1;
     65         double ll = -1.0;
     66         for( int i=1; i<=m; i++ )
     67             for( int j=i+1; j<=m; j++ ) {
     68                 double l = (bb[i]-bb[j]).len();
     69                 if( l>ll ) {
     70                     ii = i;
     71                     jj = j;
     72                     ll = l;
     73                 }
     74             }
     75         for( int i=1; i<=n; i++ )
     76             for( int j=i+1; j<=n; j++ ) 
     77                 if( onseg(aa[i],aa[j],bb[ii]) && onseg(aa[i],aa[j],bb[jj]) ) 
     78                     return true;
     79     }
     80     return false;
     81 }
     82 int main() {
     83     scanf( "%d%d", &n, &m );
     84     for( int i=1; i<=n; i++ ) {
     85         double x, y, z;
     86         scanf( "%lf%lf%lf", &x, &y, &z );
     87         aa[i] = Point(x,y);
     88     }
     89     for( int i=1; i<=m; i++ ) {
     90         double x, y, z;
     91         scanf( "%lf%lf%lf", &x, &y, &z );
     92         bb[i] = Point(x,y);
     93     }
     94     sort( bb+1, bb+1+m );
     95     m = unique( bb+1, bb+1+m ) - bb - 1;
     96     sort( aa+1, aa+1+n );
     97     n = unique( aa+1, aa+1+n ) - aa - 1;
     98     if( case1() ) {
     99         printf( "1
    " );
    100         return 0;
    101     } else if( case2() ) {
    102         printf( "2
    " );
    103         return 0;
    104     } 
    105     memset( dis, 0x3f, sizeof(dis) );
    106     for( int u=1; u<=n; u++ )
    107         for( int v=1; v<=n; v++ ) {
    108             if( u==v ) continue;
    109             bool ok = true;
    110             for( int k=1; k<=m; k++ ) 
    111                 if( !onleft(aa[u],aa[v],bb[k]) ) {
    112                     ok = false;
    113                     break;
    114                 }
    115             if( ok ) {
    116                 dis[u][v] = 1;
    117             }
    118         }
    119     for( int k=1; k<=n; k++ )
    120         for( int i=1; i<=n; i++ )
    121             for( int j=1; j<=n; j++ )
    122                 dis[i][j] = min( dis[i][j], dis[i][k]+dis[k][j] );
    123     int ans = oo;
    124     for( int i=1; i<=n; i++ ) {
    125         if( dis[i][i]==2 ) continue;
    126         ans = min( ans, dis[i][i] );
    127     }
    128     printf( "%d
    ", ans==oo ? -1 : ans );
    129 }
    View Code
  • 相关阅读:
    利用百度地图API实现百度地图坐标拾取
    newtonsoft.json的JObject里的JSON数据 动态
    监听微信返回按钮
    C# 如何理解如下泛型约束 class A<T>:where T:class{}
    微博数据库设计 _转
    新浪微博,腾讯微博mysql数据库主表猜想 __转
    Ferris教程学习笔记:js示例3.9 倒计时时钟
    Ferris教程学习笔记:js示例3.8 简易网页时钟
    Ferris教程学习笔记:js示例3.6 判断数字是否为两位数
    Ferris教程学习笔记:js示例3.5 页面加载后累加,自加1
  • 原文地址:https://www.cnblogs.com/idy002/p/4534311.html
Copyright © 2011-2022 走看看