某校由于历史悠久,校园中有大量的名胜古迹。为了更好地保护这些古迹,学校决定用篱笆将这些古迹围起来。
现在已知有p个地点的古迹需要保护。这些古迹可以看做二维平面上的整数点。有n个点可以作为篱笆的端点,这些端点的坐标也为二维平面上的整数。端点用1到n的整数编号。
有m对端点之间可以修建篱笆。用(u,v,w)描述一段可以修建的篱笆,表示端点u和端点v之间可以花费w的代价修建一段。篱笆都看做直线段。为了方便设计,这些可以修建的篱笆都是不会相交的(只会在端点处相交)。
将一个古迹围起来是指存在一个由篱笆构成的简单多边形,这个古迹在该多边形内部。
由于经费问题,学校希望修建篱笆的花费最小。你需要输出将至少1个,2个,…,p个古迹围起来的最小花费。
第一行包含三个正整数p,n,m表示古迹的个数,端点个数和可以修建的篱笆条数。
接下来p行,每行包含两个整数,表示每个古迹的坐标。
接下来n行,每行包含两个整数,表示每个端点的坐标。这些端点按照输入的顺序依次用1到n的整数编号。
最后m行,每行包含三个非负整数u,v,w,表示可以在端点u和端点v之间花w的代价修建一段篱笆。
输出p行,分别表示将至少1个,2个,…,p个古迹围起来的最小花费。
对于100%的数据,n≤100, m≤C(n,2),p≤10。所有坐标位置的两维绝对值不超过109,u,v不超过n,w不超过106。
保证可以修建的篱笆不会经过古迹。保证可以修建的两段篱笆不会在非端点处相交或重合。保证至少存在一种方案可以包围所有古迹。保证n个点互不相同。
#include<bits/stdc++.h>
#define RG register
#define il inline
#define N 10010
#define inf (1<<30)
#define LL long long
#define db double
using namespace std;
struct ed{int nxt,to,c;}e[N*2];
int head[N],tot,dep[N];
void clear(){memset(head,-1,sizeof(head));tot=0;}
void link(int u,int v,int c){e[tot].nxt=head[u];e[tot].to=v;e[tot].c=c;head[u]=tot++;}
void LINK(int u,int v,int c){link(u,v,c),link(v,u,c);}
bool BFS(int s,int t){
queue<int>que;
while(!que.empty())que.pop();
memset(dep,0,sizeof(dep));
dep[s]=1;que.push(s);
while(!que.empty()){
int u=que.front();que.pop();
for(int i=head[u];i!=-1;i=e[i].nxt){
int v=e[i].to;if(!dep[v]&&e[i].c){
dep[v]=dep[u]+1;
if(v==t)return true;
que.push(v);
}
}
}return false;
}
int dinic(int s,int t,int T){
if(s==t)return T;int tag(0);
for(int i=head[s];i!=-1;i=e[i].nxt)if(dep[e[i].to]==dep[s]+1&&e[i].c){
int v=e[i].to;
int d=dinic(v,t,min(T-tag,e[i].c));
e[i].c-=d,e[i^1].c+=d;tag+=d;
if(tag==T)break;
}if(!tag)dep[s]=0;return tag;
}
int maxflow(int s,int t){
int flow(0);
while(BFS(s,t))flow+=dinic(s,t,inf);
return flow;
}
struct point{
db x,y;
point() {}
point(db X,db Y):x(X),y(Y) {}
point operator +(const point & a)const{return point(x+a.x,y+a.y);}
point operator -(const point & a)const{return point(x-a.x,y-a.y);}
point operator *(const db & k)const{return point(x*k,y*k);}
db operator *(const point & a)const{return x*a.y-y*a.x;}
db len(){return x*x+y*y;}
void read(){scanf("%lf%lf",&x,&y);}
}p[N],a[N];
struct Line{
point st,v;
int fir,to;
int flag,val;
db k;
Line * re;
Line() {}
Line(point a,point b,int F,int T,int d):st(a),v(b),fir(F),to(T),val(d) {
flag=0;
k=atan2(v.y,v.x);
}
}l[N];
bool Comp(Line *l1,Line *l2){return l1->k<l2->k;}
vector<Line *>ex[N];
int sum,n,m,idn,BL[N];bool vis[N];
bool check(Line *l1,point p){
return (l1->v*(p-l1->st))>0;
}
bool BZ[N];
void find(Line *l1){
memset(vis,true,sizeof(vis));
for(int i=1;i<=sum;++i)if(vis[i])vis[i]=!check(l1,a[i]);
int sta=l1->fir,now=l1->to;
db s=p[l1->fir]*p[l1->to];l1->flag=idn;
do{
vector<Line * >::iterator it=upper_bound(ex[now].begin(),ex[now].end(),l1->re,Comp);
if(it==ex[now].end())
it=ex[now].begin();
l1=*it;
now=l1->to;l1->flag=idn;
l1->flag=idn;s+=p[l1->fir]*p[l1->to];
for(int i=1;i<=sum;++i)if(vis[i])vis[i]=!check(l1,a[i]);
}while(now!=sta);
for(int i=1;i<=sum;++i)if(vis[i])BL[i]=idn;
if(s>0)BZ[idn]=true;
}
int T=1100;int ans[N];
struct edge{
int fir,to,len;
edge() {}
edge(int F,int To,int W):fir(F),to(To),len(W) {
if(BZ[F])fir=T;
if(BZ[To])to=T;
}
}E[N];int sig;
int build(int x){
int num(0);clear();
for(int i=1;i<=sum;++i){
if((x>>(i-1))&1){
LINK(0,BL[i],inf);
num++;
}
}
for(int i=1;i<=sig;++i)LINK(E[i].fir,E[i].to,E[i].len);
return num;
}
int main(){
scanf("%d%d%d",&sum,&n,&m);
for(int i=1;i<=sum;++i)a[i].read();
for(int i=1;i<=n;++i)p[i].read();
for(int i=1;i<=m;++i){
int x,y,w;scanf("%d%d%d",&x,&y,&w);
l[(i<<1)-1]=Line(p[x],p[y]-p[x],x,y,w);
l[(i<<1)]=Line(p[y],p[x]-p[y],y,x,w);
l[(i<<1)-1].re=&l[(i<<1)];
l[(i<<1)].re=&l[(i<<1)-1];
ex[x].push_back(&l[(i<<1)-1]);
ex[y].push_back(&l[(i<<1)]);
}
for(int i=1;i<=n;++i)sort(ex[i].begin(),ex[i].end(),Comp);
for(int i=1;i<=2*m;++i)if(!l[i].flag)idn++,find(&l[i]);
for(int i=1;i<=2*m;i+=2)
E[++sig]=edge(l[i].flag,l[i+1].flag,l[i].val);
memset(ans,127/3,sizeof(ans));
for(int i=1;i<(1<<sum);++i){
int cnt=build(i);
ans[cnt]=min(ans[cnt],maxflow(0,T));
}
for(int i=1;i<=sum;++i)
cout<<ans[i]<<"\n";
return 0;
}