题目
这可能是我OI生涯中最长代码的题了。如果我不打紫荆花之恋的话
UPD:紫荆花之恋可以压,这个是真的压不了
明显转对偶图之后,
2
p
2^p
2p枚举包含古迹的面,将这些面与T连流量inf的边,那么面积无限的面到T的最大流就是最小割就是保护古迹的最小花费。
那么只需要把图建出来就行了(160行)。
注意(出题人保证)没有正方形套正方形(图不联通但是套在一起???)这种情况。
Claris大佬又想多了:
首先要将这个图连通,方法是通过扫描线+set求出每个连通块最高的点上方的第一条边,然后向交点连边。
然后我怎么又被卡精度了,特殊体质。
AC Code:
#include<bits/stdc++.h>
#define eps 1e-5
#define inf 0x3f3f3f3f
#define maxn 405
#define maxm 1105
using namespace std;
int dcmp(double a)
{
if(a > eps) return 1;
if(a < -eps) return -1;
return 0;
}
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
Point operator +(const Point &B)const{ return Point(x+B.x,y+B.y); }
Point operator -(const Point &B)const{ return Point(x-B.x,y-B.y); }
double operator *(const Point &B)const{ return x*B.y-y*B.x; }
bool operator <(const Point &B)const{ return dcmp(x-B.x)==0?y<B.y:x<B.x; }
}Pt[maxn];
bool cmp2(const int &u,const int &v){ return Pt[u]<Pt[v]; }
int p,n,m,loc[maxn];
struct Query
{
int id;
Point A;
bool operator <(const Query &B)const{ return dcmp(A.x-B.A.x)==0?id<B.id:A.x<B.A.x; }
}P[15];
struct edge
{
int u,v,w;
double alp;
edge(int u=0,int v=0,int w=0):u(u),v(v),w(w){alp=atan2(Pt[v].y-Pt[u].y,Pt[v].x-Pt[u].x);}
bool operator <(const edge &B)const{ return dcmp(alp-B.alp)==0?u<v:alp<B.alp; }
}e[maxm];
int id[maxm],bl[maxm],cnt_bl,infarea;
bool cmp1(const int &u,const int &v){ return e[u]<e[v]; }
int rk[maxm];
vector<int>G[maxn];
double nowx;
struct Line
{
double k,b;
int id;
Line(double k=0,double b=0,int id=0):k(k),b(b),id(id){}
bool operator <(const Line &B)const
{
double a1 = k * nowx + b , a2 = B.k * nowx + B.b;
//printf("%lf %d %d\n",nowx,id,B.id);
return dcmp(a1-a2) == 0 ? dcmp(k - B.k) == 0 ? id < B.id : k < B.k : a1 < a2;
}
};
Line calc(Point u,Point v,int id)
{
double k = (v.y-u.y) / (v.x-u.x) , b = u.y - k * u.x;
//printf("%.3lf %.3lf %d\n",k,b,id);
return Line(k,b,id);
}
set<Line>st;
set<Line>::iterator it,IT[maxm];
int info[maxn],Prev[maxm],to[maxm],cap[maxm],cnt_e=1;
void Node(int u,int v,int c){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v,cap[cnt_e]=c; }
void Lin(int u,int v,int c){ Node(u,v,c),Node(v,u,c); }
int binfo[maxn],bPrev[maxm],bcap[maxm],bcnt_e;
int bit[maxm],dis[maxm],S,T;
int aug(int now,int Max)
{
if(now == T) return Max;
int inc , st = Max;
for(int i=info[now];i;i=Prev[i])
if(cap[i] && dis[to[i]] + 1 == dis[now])
{
inc = aug(to[i] , min(cap[i] , st));
if(inc) st -= inc , cap[i] -= inc, cap[i^1] += inc;
else dis[to[i]] = -1;
if(!st) break;
}
return Max - st;
}
bool BFS()
{
static queue<int>q;
memset(dis,-1,sizeof dis);
q.push(T),dis[T]=0;
for(int now;!q.empty();)
{
now = q.front() , q.pop();
for(int i=info[now];i;i=Prev[i])
if(cap[i^1] && dis[to[i]] == -1)
{
dis[to[i]] = dis[now] + 1;
q.push(to[i]);
}
}
return dis[S] != -1;
}
int sap()
{
int stm = 0;
for(;BFS();)
stm += aug(S,inf);
return stm;
}
int ans[maxm];
int main()
{
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
scanf("%d%d%d",&p,&n,&m);
for(int i=1;i<=p;i++)
scanf("%lf%lf",&P[i].A.x,&P[i].A.y),P[i].id=i;
for(int i=1;i<=n;i++)
scanf("%lf%lf",&Pt[i].x,&Pt[i].y);
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
e[i<<1] = edge(a,b,c),id[i<<1]=(i<<1);
e[i<<1|1] = edge(b,a,c),id[i<<1|1]=(i<<1|1);
}
sort(id+2,id+2+2*m,cmp1);
for(int i=2;i<=2*m+1;i++)
{
int u = id[i];
rk[u] = G[e[u].u].size();
G[e[u].u].push_back(u);
}
for(int i=2;i<=2*m+1;i++)
if(!bl[i])
{
int eid = i , x , st = e[eid].u;
double area = 0;
for(++cnt_bl;!bl[eid];)
{
area += (Pt[e[eid].u]-Pt[st]) * (Pt[e[eid].v]-Pt[st]);
bl[eid] = cnt_bl;
x=e[eid].v , eid^=1;
if(rk[eid]==0) eid = G[x].back();
else eid = G[x][rk[eid]-1];
}
if(area < 0) infarea = cnt_bl;
}
//for(int i=2;i<=2*m+1;i++)
// printf("%d %d %d %d\n",i,e[i].u,e[i].v,bl[i]);
//GPS
for(int i=1;i<=n;i++) id[i]=i;
sort(id+1,id+1+n,cmp2);
sort(P+1,P+1+p);
for(int i=1,j=1;i<=p;i++)
{
for(;j<=n && dcmp(P[i].A.x-Pt[id[j]].x)>=0;j++)
{
int u = id[j];
for(int k=0,siz=G[u].size();k<siz;k++)
{
int eid = G[u][k];
if(dcmp(Pt[e[eid].v].x - Pt[e[eid].u].x) == 0)
continue;
if(Pt[e[eid].v].x < Pt[e[eid].u].x)
{
// puts("3");
//printf("%d %d %d\n",eid,e[eid].u,e[eid].v);
st.erase(IT[eid^1]);
}
}
nowx = Pt[u].x;
for(int k=0,siz=G[u].size();k<siz;k++)
{
int eid = G[u][k];
if(dcmp(Pt[e[eid].v].x - Pt[e[eid].u].x) == 0)
continue;
if(Pt[e[eid].v].x > Pt[e[eid].u].x)
{
// puts("4");
//printf("%d %d %d\n",eid,e[eid].u,e[eid].v);
// printf("%.3lf %.3lf %.3lf %.3lf\n",Pt[e[eid].u].x,Pt[e[eid].u].y,Pt[e[eid].v].x,Pt[e[eid].v].y);
IT[eid] = st.insert(calc(Pt[e[eid].v],Pt[e[eid].u],eid)).first;
}
}
}
if(st.empty())
{
loc[P[i].id] = infarea;
continue;
}
nowx = P[i].A.x;
it = st.lower_bound(Line(0,P[i].A.y,0));
if(it == st.begin() || it == st.end())
{
//puts("1");
loc[P[i].id] = infarea;
}
else
{
loc[P[i].id] = bl[(*(--it)).id];
//puts("2");
}
}//puts("5");
for(int i=1;i<=m;i++)
if(bl[i<<1] != bl[i<<1|1])
Lin(bl[i<<1],bl[i<<1|1],e[i<<1].w);
memcpy(binfo,info,sizeof info);
memcpy(bPrev,Prev,sizeof Prev);
memcpy(bcap,cap,sizeof cap);
bcnt_e = cnt_e; // !!
//printf("%d\n",infarea);
S = infarea , T = cnt_bl + 1;
memset(ans,0x3f,sizeof ans);
for(int i=1;i<(1<<p);i++)
{
memcpy(info,binfo,sizeof info);
memcpy(Prev,bPrev,sizeof Prev);
memcpy(cap,bcap,sizeof cap);
cnt_e=bcnt_e;
bit[i] = bit[i>>1] + (i&1);
for(int j=1;j<=p;j++)
if(i>>(j-1)&1)
Lin(loc[j],T,inf);
ans[bit[i]] = min(ans[bit[i]] , sap());
//printf("%d\n",i);
}
for(int i=p;i>=1;i--)
ans[i] = min(ans[i] , ans[i+1]);
for(int i=1;i<=p;i++)
printf("%d\n",ans[i]);
}