zoukankan      html  css  js  c++  java
  • bzoj2965

    http://www.lydsy.com/JudgeOnline/problem.php?id=2965

    http://www.tsinsen.com/A1385

    平面图网络流。

    首先我们要将平面图转化成对偶图。

    将每条无向边拆成两个向量,从一条未访问过的向量开始,找到逆时针方向上第一个向量,然后继续访问,直到形成环,这样就找到了一条轮廓线,且内部在向量的右边。

    如图从为访问过的边1->8开始,找到8->7,然后继续找到7->1,形成了环,这样找到了一条轮廓线。内部在1->8,8->7,7->1的右边。

    我们称这种轮廓线为内轮廓线

    (图1)

    但是如果从1->2开始找,会找到下图这样的轮廓线,并且我们认为多边形在向量的右边。

    我们称这种轮廓线为外轮廓线

    (图2)

    内轮廓线(图1)和外轮廓线(图2)的区别是:内轮廓线的点的顺序是顺时针,外轮廓线的点的顺序是逆时针。

    这种情况我们可以用有向面积判断。

    如果点的顺序是顺时针,那么有向面积为负,如图1;如果点的顺序是逆时针,那么有向面积为正,如图2。

    这样我们就区分了内轮廓线和外轮廓线。

    现在我们找出了全部轮廓线,接下来求域。

    为了方便,我们在原图的基础上用一个足够大的矩形”框"住所有点。

    我们称连通的空白部分为

    我们称外部的无限区域为无限域。无限域是这样的(虚线为外轮廓线,灰色部分为无限域)

    (图3)

    无限域有且仅有一个,且只有一条外轮廓线,因为我们用了一个足够大的矩形”框"住所有点。

    除无限域外,其他的域称为有限域。有限域是这样的(实线为内轮廓线,虚线为外轮廓线,灰色部分为有限域):

    (图4)

    有限域一定有一条内轮廓线,可能有若干条外轮廓线。

    内轮廓线一定与有限域对应,外轮廓线可能与有限域或无限域对应。

    我们怎么找外轮廓线对应的有限域或无限域呢?

    如果没有内轮廓线严格包住外轮廓线,那么这条外轮廓线对应唯一的无限域,如图3。

    如果有内轮廓线严格包住这条外轮廓线,我们就找严格包住这条外轮廓线的面积最小的内轮廓线,那么这条外轮廓线对应的有限域就是这条内轮廓线对应的有限域。

    判断外轮廓线有没有被某条内轮廓线可以随便取外轮廓线上的一点,然后用射线法判断这个点是否严格在内轮廓线(即判断一个点是否在简单多边形内)。

    现在已经把域求出来了。

    我们还判断古迹属于哪个域。

    直接找到严格包住这个古迹的面积最小的内轮廓线(即简单多边形),判断古迹是否被严格包含可以用射线法(即判断一个点是否在简单多边形内)。

    接下来就是网络流的建图了。

    每个域看成一个结点,无限域就是汇点T。

    一条边两侧的两个域我们已经求出来的,直接在这两个域之间连一条容量为建篱笆代价的边。

    由于只有10个古迹,我们直接2^10枚举哪些古迹一定要被围起来。

    如果某个古迹一定要被围起来,就从源点S到这个古迹所在的域连边。

    根据最大流最小割定理,直接跑网络流即可。

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<fstream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<vector>
    #include<functional>
    #include<deque>
    #include<cctype>
    #include<climits>
    #include<complex>
    //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
     
    using namespace std;
    
    typedef long long LL;
    typedef double DB;
    typedef pair<int,int> PII;
    typedef complex<DB> CP;
    
    #define mmst(a,v) memset(a,v,sizeof(a))
    #define mmcy(a,b) memcpy(a,b,sizeof(a))
    #define fill(a,l,r,v) fill(a+l,a+r+1,v)
    #define re(i,a,b)  for(i=(a);i<=(b);i++)
    #define red(i,a,b) for(i=(a);i>=(b);i--)
    #define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)
    #define fi first
    #define se second
    #define m_p(a,b) make_pair(a,b)
    #define SF scanf
    #define PF printf
    #define p_b push_back
    #define two(k) (1<<(k))
    
    template<class T>inline T sqr(T x){return x*x;}
    template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
    template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}
    
    const DB EPS=1e-9;
    inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
    const DB Pi=acos(-1.0);
    
    inline int gint()
      {
            int res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    inline LL gll()
      {
          LL res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    
    const int maxP=10;
    const int maxN=100+4;
    const int maxM=maxN*(maxN-1)/2;
    const int maxcnt=maxM+2-maxN;
    const LL INF=1LL<<50;
    
    struct Tpoint
      {
          int x,y;
          inline Tpoint(int _x=0,int _y=0){x=_x;y=_y;}
          inline void input(){x=gint();y=gint();}
      };
    
    struct Tseg
      {
          Tpoint st,en;
          DB alpha;
          int id,u,v,flag;
          LL cost;
          Tseg *another;
          inline Tseg(Tpoint _st=Tpoint(),Tpoint _en=Tpoint(),int _u=0,int _v=0,LL _cost=0){st=_st;en=_en;u=_u;v=_v;cost=_cost;alpha=atan2(en.y-st.y,en.x-st.x);id=0;flag=0;another=0;}
      };
    
    inline LL det(Tpoint p0,Tpoint p1,Tpoint p2){return LL(p1.x-p0.x)*LL(p2.y-p0.y)-LL(p2.x-p0.x)*LL(p1.y-p0.y);}
    
    int P,N,M;
    Tpoint arch[maxP+10],p[maxN+10];
    Tseg line[2*maxM+100];
    int belong[maxP+10];
    LL ans[maxP+10];
    
    vector<Tseg*> e[maxN+10];
    inline bool cmp(Tseg *a,Tseg *b){return a->alpha<b->alpha;}
    
    inline void insertline(int i,int u,int v,LL cost)
      {
          line[i<<1]=Tseg(p[u],p[v],u,v,cost);
          line[i<<1^1]=Tseg(p[v],p[u],v,u,cost);
          line[i<<1].another=&line[i<<1^1];
          line[i<<1^1].another=&line[i<<1];
          e[u].p_b(&line[i<<1]);
          e[v].p_b(&line[i<<1^1]);
          line[i<<1].id=i<<1;
          line[i<<1^1].id=i<<1^1;
      }
    
    int cnt;
    struct Thull
      {
          int n;
          LL area;//如果点的顺序是顺时针,area为负数;如果点的顺序是逆时针,area为正数
          Tpoint a[maxN+100];
          int eid[maxN+100];
          inline void insert(Tpoint x,int t){n++;a[n]=x;eid[n]=t;}
      }h[maxcnt+100];
    int out[maxcnt+100];
    
    inline int inhull(Thull &plg,const Tpoint &a) 
      {
          int i,count = 0;
          int d1,d2,d3;
          plg.a[plg.n+1]= plg.a[1];
          re(i,1,plg.n)
            {
                if(plg.a[i].x==a.x && plg.a[i].y==a.y) return 0;
              d1=plg.a[i+1].y-plg.a[i].y;
              d2=a.y-plg.a[i].y;
              d3=plg.a[i+1].y-a.y;
              if (d1>0 && d2>0 && d3>=0 && det(plg.a[i],plg.a[i+1],a)>0) count++;
              if (d1<0 && d2<=0 && d3<0 && det(plg.a[i+1],plg.a[i],a)>0) count++;
            }
          return count&1;
      }
    
    inline void find(Tseg *l)
      {
          int i;
          ++cnt;
          int start=l->u,now=l->v;
          LL area=det(Tpoint(),l->st,l->en);
          l->flag=cnt;
          h[cnt].insert(p[now],l->id);
          while(now!=start)
            {
                vector<Tseg*>::iterator it=upper_bound(e[now].begin(),e[now].end(),l->another,cmp);
                if(it==e[now].end())it=e[now].begin();
                l=*it;
                area+=det(Tpoint(),l->st,l->en);
                l->flag=cnt;
                now=l->v;
                h[cnt].insert(p[now],l->id);
            }
          h[cnt].area=area;
            out[cnt]=(area>0);
            if(!out[cnt])
              {
                  re(i,1,P)
                      if(inhull(h[cnt],arch[i]))
                        if(!belong[i] || abs(h[cnt].area)<abs(h[belong[i]].area))
                          belong[i]=cnt;
              }
        }
    
    inline void check(int r)
      {
          int i,be=-1;
          re(i,1,cnt)if(out[i]==0)
            if(inhull(h[i],h[r].a[1]))
              if(be==-1 || abs(h[i].area)<abs(h[be].area))
                be=i;
          if(be==-1)return;
          re(i,1,h[r].n)line[h[r].eid[i]].flag=be;
          out[r]=2;
      }
    
    int S,T,now,first[maxcnt+100],last[maxcnt+100];
    struct Tedge{int v,next;LL flow;}edge[2*(maxP+2*maxM)+1000000];
    inline void insert(int u,int v,LL flow)
      {
          now++;edge[now].v=v;edge[now].flow=flow;edge[now].next=first[u];first[u]=now;
          now++;edge[now].v=u;edge[now].flow=0;edge[now].next=first[v];first[v]=now;
      }
    inline int flow_build(int state)
      {
          int i,res=0;
          S=0;re(i,1,cnt)if(out[i]==1)T=i;
          mmst(first,-1);now=-1;
          #define wei(state,k) ((state>>(k-1))&1)
          re(i,1,P)if(wei(state,i))res++,insert(S,belong[i],INF);
          for(i=2;i<=(M<<1^1);i+=2)
            {
                int u=line[i].flag,v=line[i^1].flag;LL flow=line[i].cost;
                insert(u,v,flow);
                insert(v,u,flow);
            }
          return res;
      }
    
    int head,tail,que[maxcnt+100];
    int level[maxcnt+100];
    inline int Dinic_Build()
      {
          int i;
          re(i,0,cnt)level[i]=0;
          level[que[head=tail=0]=S]=1;
          while(head<=tail)
            {
                int u=que[head++],v;LL flow;
                for(i=first[u],v=edge[i].v,flow=edge[i].flow;i!=-1;i=edge[i].next,v=edge[i].v,flow=edge[i].flow)
                  if(flow>0 && !level[v])
                    level[que[++tail]=v]=level[u]+1;
            }
          return level[T];
      }
    inline LL Dinic(int u,LL delta)
      {
          if(u==T)return delta;
          LL res=0;int &i=last[u],v;LL flow;
          for(v=edge[i].v,flow=edge[i].flow;i!=-1;i=edge[i].next,v=edge[i].v,flow=edge[i].flow)
            if(flow>0 && level[u]+1==level[v])
              {
                  LL temp=Dinic(v,min(flow,delta));
                  delta-=temp;
                  res+=temp;
                  edge[i].flow-=temp;
                  edge[i^1].flow+=temp;
                  if(delta==0)return res;
              }
          return res;
      }
    
    int main()
      {
          freopen("bzoj2965.in","r",stdin);
          freopen("bzoj2965.out","w",stdout);
          int i;
          P=gint();N=gint();M=gint();
          re(i,1,P)arch[i].input();
          int minx=1<<30,maxx=-1<<30,miny=1<<30,maxy=-1<<30;
          re(i,1,N){p[i].input();upmin(minx,p[i].x);upmax(maxx,p[i].x);upmin(miny,p[i].y);upmax(maxy,p[i].y);}
          minx--;maxx++;miny--;maxy++;
          p[++N]=Tpoint(maxx,maxy);
          p[++N]=Tpoint(maxx,miny);
          p[++N]=Tpoint(minx,miny);
          p[++N]=Tpoint(minx,maxy);
          re(i,1,M){int u=gint(),v=gint();LL cost=gll();insertline(i,u,v,cost);}
          insertline(++M,N-3,N-2,INF);
          insertline(++M,N-2,N-1,INF);
          insertline(++M,N-1,N,INF);
          insertline(++M,N,N-3,INF);
          re(i,1,N)sort(e[i].begin(),e[i].end(),cmp);
          re(i,2,M<<1^1)if(!line[i].flag)find(&line[i]);
          re(i,1,cnt)if(out[i]==1)check(i);
          mmst(ans,0x3f);
          for(int state=1;state<1<<P;state++)
            {
                int ge=flow_build(state);LL maxflow=0;
                while(Dinic_Build())
                  {
                      re(i,0,cnt+1)last[i]=first[i];
                      maxflow+=Dinic(S,INF);
                  }
                upmin(ans[ge],maxflow);
            }
          re(i,1,P)cout<<ans[i]<<endl;
          return 0;
      }
    View Code

    我现在的心情就像一个去了皮的大土豆~OTATO

  • 相关阅读:
    今天VSS 了一把
    中文字母检索
    当心! 您也可能犯得js错 eval()不等于eval("")!
    腾讯微博邀请码2010年6月9日11:14:28
    存储过程原理
    腾讯微博邀请码2010年5月25日16:44:24
    《QQ我的好友想到的信息架构》
    8小时之外(Beyond the 8 Hours)
    超搞笑漫画比喻!如果浏览器是出行工具
    Nginx环境下配置PHP使用的SSL认证(https)
  • 原文地址:https://www.cnblogs.com/maijing/p/4708247.html
Copyright © 2011-2022 走看看