码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj2965

时间:2015-08-06 21:41:18      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:

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到这个古迹所在的域连边。

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

 

这个代码在清澄上A了,但我用的方法是错的,数据好弱。

技术分享
#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;
const int maxM=maxN*(maxN-1)/2;
const int maxcnt=maxM+2-maxN;
const int INF=1<<30;
 
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 u,v,len,flag;
    Tseg *another;
    inline Tseg(Tpoint _st=Tpoint(),Tpoint _en=Tpoint(),int _u=0,int _v=0,int _len=0){st=_st;en=_en;u=_u;v=_v;len=_len;alpha=atan2(en.y-st.y,en.x-st.x);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];
int ans[maxP+10];
 
vector<Tseg*> e[maxN+10];
inline bool cmp(Tseg *a,Tseg *b){return a->alpha<b->alpha;}
 
int cnt;
int out[maxcnt+100];
 
inline int onright(Tseg *l,Tpoint p){return det(l->st,l->en,p)<0;}
 
inline void find(Tseg *l)
  {
    int i;
    static int f[maxN+10];re(i,1,P)f[i]=1;
    ++cnt;
    int start=l->u,now=l->v;
    LL area=det(Tpoint(),l->st,l->en);
    l->flag=cnt;
    re(i,1,P)f[i]&=onright(l,arch[i]);
    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;
        re(i,1,P)f[i]&=onright(l,arch[i]);
        now=l->v;
      }
    re(i,1,P)if(f[i])belong[i]=cnt;
    //如果点的顺序是顺时针,area为负数
    //如果点的顺序是逆时针,area为正数
    out[cnt]=(area>0);
  }
 
int S,T,now,first[maxcnt+100],last[maxcnt+100];
struct Tedge{int v,flow,next;}edge[2*(maxP+2*maxM)+1000000];
inline void insert(int u,int v,int 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;T=cnt+1;
    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);
    re(i,1,cnt)if(out[i])insert(i,T,INF);
    for(i=2;i<=(M<<1^1);i+=2)
      {
        int u=line[i].flag,v=line[i^1].flag,flow=line[i].len;
        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+1)level[i]=0;
    level[que[head=tail=0]=S]=1;
    while(head<=tail)
      {
        int u=que[head++],v,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 int Dinic(int u,int delta)
  {
    if(u==T)return delta;
    int res=0,&i=last[u],v,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])
        {
            int 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();
    re(i,1,N)p[i].input();
    re(i,1,M)
      {
        int u=gint(),v=gint(),len=gint();
        line[i<<1]=Tseg(p[u],p[v],u,v,len);
        line[i<<1^1]=Tseg(p[v],p[u],v,u,len);
        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]);
      }
    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]);
    mmst(ans,0x3f);
    for(int state=1;state<1<<P;state++)
      {
        int ge=flow_build(state),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

技术分享

如下面这个数据就可以hack了。

技术分享
1 8 8
0 0
1 1
1 -1
-1 -1
-1 1
2 2
2 -2
-2 -2
-2 2
1 2 1
2 3 1
3 4 1
4 1 1
5 6 100
6 7 100
7 8 100
8 5 100
View Code

 

这是我认为是对的,然而在清澄上却W了。

技术分享
#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 count = 0;
      int d1,d2,d3;
      plg.a[plg.n+1]= plg.a[1];
      for (int i=1; i<=plg.n; i++)
        {
          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

bzoj2965

标签:

原文地址:http://www.cnblogs.com/maijing/p/4708247.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!