记录编号 236192 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [JLOI 2014]镜面通道 最终得分 100
用户昵称 Gravatarzys 是否通过 通过
代码语言 C++ 运行时间 3.836 s
提交时间 2016-03-13 09:46:23 内存使用 5.20 MiB
显示代码纯文本
#define maxn 400
#define ll long long
#define dot2(x) (x<<1)
#define dot1(x) ((x<<1)-1)
#define rec(x) p[x].r
#define typ(x) p[x].type
#define circle(x) p[x].c
#define recl(x) p[x].r.left_low
#define recr(x) p[x].r.right_up
#define Min(a,b)((a)<(b)?(a):(b))
#define circle_center(x) p[x].c.center


#include<cmath>
#include<cstdio>
#include<cstring>

using namespace std;

const int inf=0x2fffffff;
int n,right_boundary,up_boundary,cnt;ll dis;
int s,t,tot,first[maxn<<2],d[maxn<<2],q[maxn<<2],head,tail,cx,cy,cr,flow,ans;

struct Edge{
    int u,v,next,w;
}edge[maxn*maxn<<1];

struct point{
    int x,y;
};

struct circle{
    point center;int r;
};

struct rectangle{
    point left_low,right_up;
};

struct component{
    bool type;
    circle c;rectangle r;
}p[maxn];

void add(int u,int v,int w)
{
    edge[tot].u=u;
    edge[tot].v=v;
    edge[tot].w=w;
    edge[tot].next=first[u];
    first[u]=tot++;
}

void Add(int u,int v,int w)
{
    add(u,v,w);add(v,u,0);
}

bool bfs()
{
    memset(d,0,sizeof(d));
    head=tail=0;q[tail]=s;d[s]=1;
    while(head<=tail){
        int p=q[head++];
        for(int i=first[p];i!=-1;i=edge[i].next)
            if(edge[i].w>0&&(!d[edge[i].v])){
                d[edge[i].v]=d[p]+1;
                if(edge[i].v==t)return true;
                q[++tail]=edge[i].v;
            }
    }
    return false;
}

int dinic(int now,int f)
{
    if(now==t||(!f))return f;
    int tmp=f;
    for(int i=first[now];i!=-1;i=edge[i].next)
        if(edge[i].w>0&&d[edge[i].v]==d[now]+1){
            int k=dinic(edge[i].v,Min(f,edge[i].w));
            if(!k)d[edge[i].v]=0;
            edge[i].w-=k;edge[i^1].w+=k;f-=k;
            if(!f)break;
        }
    return tmp-f;
}

bool point_in_cir(point x,circle c)
{
    return (ll)(x.x-c.center.x)*(ll)(x.x-c.center.x)+(ll)(x.y-c.center.y)*(ll)(x.y-c.center.y)<=(ll)c.r*(ll)c.r;
}

bool point_in_rec(point x,rectangle r)
{
    return x.x<=r.right_up.x&&x.x>=r.left_low.x&&x.y<=r.right_up.y&&x.y>=r.left_low.y;
}

bool cross_circle(circle c1,circle c2)
{
    dis=(ll)(c1.center.x-c2.center.x)*(ll)(c1.center.x-c2.center.x)+(ll)(c1.center.y-c2.center.y)*(ll)(c1.center.y-c2.center.y);
    return (dis<=(ll)(c1.r+c2.r)*(ll)(c1.r+c2.r))&&(dis>(ll)(c1.r-c2.r)*(ll)(c1.r-c2.r));
}

bool cross_rec_circle(circle c,rectangle r)
{
    cx=c.center.x;cy=c.center.y;cr=c.r;cnt=0;
    if(cx+cr<=r.right_up.x&&cx-cr>=r.left_low.x&&cy+cr<=r.right_up.y&&cy-cr>=r.left_low.y)return false;
    if(point_in_cir(r.left_low,c))cnt++;
    if(point_in_cir(r.right_up,c))cnt++;
    if(point_in_cir((point){r.left_low.x,r.right_up.y},c))cnt++;
    if(point_in_cir((point){r.right_up.x,r.left_low.y},c))cnt++;
    if(cnt>0&&cnt<4)return true;
    if((ll)(cx-r.right_up.x)*(ll)(cx-r.right_up.x)<=(ll)cr*(ll)cr&&r.right_up.y>=cy&&r.left_low.y<=cy)return true;
    if((ll)(cy-r.right_up.y)*(ll)(cy-r.right_up.y)<=(ll)cr*(ll)cr&&r.right_up.x>=cx&&r.left_low.x<=cx)return true;
    if((ll)(cx-r.left_low.x)*(ll)(cx-r.left_low.x)<=(ll)cr*(ll)cr&&r.right_up.y>=cy&&r.left_low.y<=cy)return true;
    if((ll)(cy-r.left_low.y)*(ll)(cy-r.left_low.y)<=(ll)cr*(ll)cr&&r.right_up.x>=cx&&r.left_low.x<=cx)return true;
    return false;
}

bool cross_rec(rectangle r1,rectangle r2)
{
    cnt=0;
    if(point_in_rec(r2.left_low,r1))cnt++;
    if(point_in_rec(r2.right_up,r1))cnt++;
    if(point_in_rec((point){r2.left_low.x,r2.right_up.y},r1))cnt++;
    if(point_in_rec((point){r2.right_up.x,r2.left_low.y},r1))cnt++;
    if((!cnt)||cnt==4)return false;return true;
}

void renew(){for(int i=0;i<tot;i+=2) edge[i].w+=edge[i^1].w,edge[i^1].w=0;}

int min_cut()
{
    int maxflow=0;
    while(bfs())while(flow=dinic(s,inf)) maxflow+=flow;
    return maxflow;
}

int main()
{
	freopen("JLOI_mirror.in","r",stdin);
	freopen("JLOI_mirror.out","w",stdout);
    memset(first,-1,sizeof(first));
    scanf("%d%d%d",&right_boundary,&up_boundary,&n);t=(n<<1)+1;
    for(int i=1,k;i<=n;i++){
        scanf("%d",&k);
        if(k==1)scanf("%d%d%d",&circle_center(i).x,&circle_center(i).y,&circle(i).r),typ(i)=1;
        else scanf("%d%d%d%d",&recl(i).x,&recl(i).y,&recr(i).x,&recr(i).y),typ(i)=0;
    }
    for(int i=1;i<=n;i++)Add(dot1(i),dot2(i),1);
    for(int i=1;i<=n;i++)
        if(typ(i)&&circle_center(i).y+circle(i).r>=up_boundary)Add(s,dot1(i),inf);
        else if((!typ(i))&&recr(i).y>=up_boundary)Add(s,dot1(i),inf);
    for(int i=1;i<=n;i++)
        if(typ(i)&&circle_center(i).y-circle(i).r<=0)Add(dot2(i),t,inf);
        else if(!typ(i)&&recl(i).y<=0)Add(dot2(i),t,inf);
    for(int i=n;i>=1;i--)for(int j=n;j>i;j--){
        if(typ(i)&&typ(j)){if(cross_circle(circle(i),circle(j)))Add(dot2(i),dot1(j),inf),Add(dot2(j),dot1(i),inf);}
        else if((typ(i)&&(!typ(j)))||(typ(j)&&(!typ(i)))){
            if(typ(i)){if(cross_rec_circle(circle(i),rec(j)))Add(dot2(i),dot1(j),inf),Add(dot2(j),dot1(i),inf);}
            else if(cross_rec_circle(circle(j),rec(i)))Add(dot2(i),dot1(j),inf),Add(dot2(j),dot1(i),inf);
        }
        else{if(cross_rec(rec(i),rec(j)))Add(dot2(i),dot1(j),inf),Add(dot2(j),dot1(i),inf);}
    }
    while(bfs())while(flow=dinic(s,inf))ans+=flow;printf("%d\n",ans);
    for(int i=1;i<=n;i++){
		renew(),edge[(i<<1)-2].w=0;
		if(min_cut()==ans-1) ans--,printf("%d ",i);
		else edge[(i<<1)-2].w=1;
	}
}