bzoj2965
http://www.lydsy.com/JudgeOnline/problem.php?id=2965
平面图网络流。
首先我们要将平面图转化成对偶图。
将每条无向边拆成两个向量,从一条未访问过的向量开始,找到逆时针方向上第一个向量,然后继续访问,直到形成环,这样就找到了一条轮廓线,且内部在向量的右边。
如图从为访问过的边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-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxP=;
const int maxN=+;
const int maxM=maxN*(maxN-)/;
const int maxcnt=maxM+-maxN;
const LL INF=1LL<<; struct Tpoint
{
int x,y;
inline Tpoint(int _x=,int _y=){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=,int _v=,LL _cost=){st=_st;en=_en;u=_u;v=_v;cost=_cost;alpha=atan2(en.y-st.y,en.x-st.x);id=;flag=;another=;}
}; 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+],p[maxN+];
Tseg line[*maxM+];
int belong[maxP+];
LL ans[maxP+]; vector<Tseg*> e[maxN+];
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<<]=Tseg(p[u],p[v],u,v,cost);
line[i<<^]=Tseg(p[v],p[u],v,u,cost);
line[i<<].another=&line[i<<^];
line[i<<^].another=&line[i<<];
e[u].p_b(&line[i<<]);
e[v].p_b(&line[i<<^]);
line[i<<].id=i<<;
line[i<<^].id=i<<^;
} int cnt;
struct Thull
{
int n;
LL area;//如果点的顺序是顺时针,area为负数;如果点的顺序是逆时针,area为正数
Tpoint a[maxN+];
int eid[maxN+];
inline void insert(Tpoint x,int t){n++;a[n]=x;eid[n]=t;}
}h[maxcnt+];
int out[maxcnt+]; inline int inhull(Thull &plg,const Tpoint &a)
{
int i,count = ;
int d1,d2,d3;
plg.a[plg.n+]= plg.a[];
re(i,,plg.n)
{
if(plg.a[i].x==a.x && plg.a[i].y==a.y) return ;
d1=plg.a[i+].y-plg.a[i].y;
d2=a.y-plg.a[i].y;
d3=plg.a[i+].y-a.y;
if (d1> && d2> && d3>= && det(plg.a[i],plg.a[i+],a)>) count++;
if (d1< && d2<= && d3< && det(plg.a[i+],plg.a[i],a)>) count++;
}
return count&;
} 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>);
if(!out[cnt])
{
re(i,,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=-;
re(i,,cnt)if(out[i]==)
if(inhull(h[i],h[r].a[]))
if(be==- || abs(h[i].area)<abs(h[be].area))
be=i;
if(be==-)return;
re(i,,h[r].n)line[h[r].eid[i]].flag=be;
out[r]=;
} int S,T,now,first[maxcnt+],last[maxcnt+];
struct Tedge{int v,next;LL flow;}edge[*(maxP+*maxM)+];
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=;edge[now].next=first[v];first[v]=now;
}
inline int flow_build(int state)
{
int i,res=;
S=;re(i,,cnt)if(out[i]==)T=i;
mmst(first,-);now=-;
#define wei(state,k) ((state>>(k-1))&1)
re(i,,P)if(wei(state,i))res++,insert(S,belong[i],INF);
for(i=;i<=(M<<^);i+=)
{
int u=line[i].flag,v=line[i^].flag;LL flow=line[i].cost;
insert(u,v,flow);
insert(v,u,flow);
}
return res;
} int head,tail,que[maxcnt+];
int level[maxcnt+];
inline int Dinic_Build()
{
int i;
re(i,,cnt)level[i]=;
level[que[head=tail=]=S]=;
while(head<=tail)
{
int u=que[head++],v;LL flow;
for(i=first[u],v=edge[i].v,flow=edge[i].flow;i!=-;i=edge[i].next,v=edge[i].v,flow=edge[i].flow)
if(flow> && !level[v])
level[que[++tail]=v]=level[u]+;
}
return level[T];
}
inline LL Dinic(int u,LL delta)
{
if(u==T)return delta;
LL res=;int &i=last[u],v;LL flow;
for(v=edge[i].v,flow=edge[i].flow;i!=-;i=edge[i].next,v=edge[i].v,flow=edge[i].flow)
if(flow> && level[u]+==level[v])
{
LL temp=Dinic(v,min(flow,delta));
delta-=temp;
res+=temp;
edge[i].flow-=temp;
edge[i^].flow+=temp;
if(delta==)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,,P)arch[i].input();
int minx=<<,maxx=-<<,miny=<<,maxy=-<<;
re(i,,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,,M){int u=gint(),v=gint();LL cost=gll();insertline(i,u,v,cost);}
insertline(++M,N-,N-,INF);
insertline(++M,N-,N-,INF);
insertline(++M,N-,N,INF);
insertline(++M,N,N-,INF);
re(i,,N)sort(e[i].begin(),e[i].end(),cmp);
re(i,,M<<^)if(!line[i].flag)find(&line[i]);
re(i,,cnt)if(out[i]==)check(i);
mmst(ans,0x3f);
for(int state=;state<<<P;state++)
{
int ge=flow_build(state);LL maxflow=;
while(Dinic_Build())
{
re(i,,cnt+)last[i]=first[i];
maxflow+=Dinic(S,INF);
}
upmin(ans[ge],maxflow);
}
re(i,,P)cout<<ans[i]<<endl;
return ;
}
我现在的心情就像一个去了皮的大土豆~OTATO
bzoj2965的更多相关文章
- BZOJ2965 : 保护古迹
首先要将这个图连通,方法是通过扫描线+set求出每个连通块最高的点上方的第一条边,然后向交点连边. 然后把边拆成两条双向边,每次找到一条没走过的边,找到极角排序后它的反向边的后继,直到回到这条边. 根 ...
随机推荐
- 转:史上最全最强SpringMVC详细示例实战教程
一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar包. 2.添加Web.xml配置文件中关于SpringMVC的配置 <!--conf ...
- 在jsp页面上直接打开PDF文件
1.在不需要使用插件,直接打开通过链接方式打开 <%@ page language="java" import="java.util.*,java.io.*&quo ...
- JavaScript兼容问题汇总[实时更新]
印象笔记链接地址:点我查看 遇到问题不断更新中-- [转载请注明出处-HTML5自由者]
- 局域网指定 IP 地址后无法上网的问题
子网掩码.默认网关.DNS 与局域网设置有关,建议指定前先 运行 cmd -> ipconfig /all 查看一下自动获取的信息. 另外留意指定IP 后需打开高级设置 -> WINS,勾 ...
- 设计模式2----建造者模式(builder pattern)
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 类型:创建类模式 类图: UML图 四个要素 Builder: 抽象建造者ConcreteBuilder: 具体建造者 ...
- mybatis知识总结
基于昨天的mybatis入门详解,今天我们再来看看mybatis稍微高深些的知识点. 1.解决Model属性和数据库字段不一致的问题 1),开启驼峰命名 2),使用resultMap进行映射, < ...
- wpf-DataTemplate应用
在WPF中,决定数据外观的是DataTemplate,即DataTemplate是数据内容的表现形式,一条数据显示成什么样子,是简单的文本还是直观的图形,就是由DataTemplate决定的.下面通过 ...
- jQuery下的显示和隐藏
因为太久没更新了,所以来放一点没意思的内容. 做的是jQuery框架的隐藏和显示,HTML如下: <ul> <li>1</li> <li>2</l ...
- 关于winform主题IrisSkin2的编写
第一步:首先引用IrisSkin2.dll. 第二步自定义类: /// <summary> /// 窗体主题边界类 /// </summary> public class Fo ...
- 22 java常用方法
/** * 通过正则获取该目录下满足条件的所有目录 * @param luceneFilePathRegular 正则目录,如/user/solrindex/正则表达式 * @return 满足正则表 ...