# bzoj1035

### 1035: [ZJOI2008]Risk

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 64   Solved: 19
[ Submit][ Status][ Discuss]

4 12
3 2
11 8
12 17
1 19
0 0 10 0
10 0 20 0
20 0 20 10
20 10 20 20
20 20 10 20
10 20 0 20
0 20 0 10
0 10 0 0
10 0 10 10
0 10 10 10
20 10 10 10
10 20 10 10

### Sample Output

2 2 4
2 1 3
2 2 4
2 1 3

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
using namespace std;
double pi,eps,z;
int tot,n,m,i,j,k,o,all,coun[601],xl[8001],x[601],y[601],x1[8001],y11[8001],x2[8001],y2[8001],dl[8001],belong[8001];
int incl[601][601],w[601],p[601],linkk[601][601],who[601],oo[601][601],ans[601][601];
bool ok[601];

bool wwwww (int a,int b)
{
return p[a]>p[b];
}

bool cmp (int a,int b)
{
return x1[a]*10000+y11[a]<x1[b]*10000+y11[b];
}

int anti (int x)
{
if (x>m) return x-m;
else     return x+m;
}

bool meet (double x1,double y11,double x2,double y2,double q1,double p1,double q2,double p2)
{
if (((fabs(x1-q1)<=eps)&(fabs(y11-p1)<=eps))||((fabs(x1-q2)<=eps)&(fabs(y11-p2)<=eps))) return false;
if (fabs(q1-q2)<=eps)
if (((fabs(x1-q1)<=eps)&(p1<=y11)&(y11<=p2))||
((fabs(x2-q1)<=eps)&(p1<=y2)&(y2<=p2)))
return true;
else
return false;
double k1,b1,k2,b2,x,y;
k1=(y2-y11)/(x2-x1);
b1=y11-k1*x1;
k2=(p2-p1)/(q2-q1);
b2=p1-k2*q1;
x=(b2-b1)/(k1-k2);
y=x*k1+b1;
if (q1>q2) swap(q1,q2);
return ((x1<=x)&(x<=x2)&(q1<=x)&(x<=q2));
}

double calc (double x1,double y11,double x2,double y2)
{
double x,y;
x=x2-x1;
y=y2-y11;

if (x==0)
if (y>0) return pi/2;
else     return pi+pi/2;

if (y==0)
if (x<0) return 0;
else     return pi;

if ((x<0)&(y>0)) return asin(y/(x*x+y*y));
if ((x>0)&(y>0)) return pi-asin(y/(x*x+y*y));
if ((x>0)&(y<0)) return acos(x/(x*x+y*y))+pi;
if ((x<0)&(y<0)) return 2*pi-acos(-x/(x*x+y*y));
}

double quick (int a,int b)
{
double x,y,o;
x=calc(x2[a],y2[a],x1[a],y11[a]);
y=calc(x1[b],y11[b],x2[b],y2[b]);
if (x>y) return y+2*pi-x;
else     return y-x;
}

int main ()
{
eps=1e-7;
pi=3.1415926535897932384626433;
scanf("%d %d",&n,&m);
for (i=1;i<=n;i++)
scanf("%d %d",&x[i],&y[i]);
for (i=1;i<=m;i++)
{
scanf("%d %d %d %d",&x1[i],&y11[i],&x2[i],&y2[i]);
x1[i+m]=x2[i];
y11[i+m]=y2[i];
x2[i+m]=x1[i];
y2[i+m]=y11[i];
}
for (i=1;i<=2*m;i++)
dl[i]=i;
sort(dl+1,dl+2*m+1,cmp);
for (i=1;i<=m*2;i++)
if (belong[dl[i]]==0)
{
k=dl[i];
tot++;
belong[k]=tot;
all=0;
z=0;
do
{
int s,e,mid;
s=1;
e=m*2;
while (s!=e)
{
mid=(s+e)/2;
if (x1[dl[mid]]*10000+y11[dl[mid]]<x2[k]*10000+y2[k])
s=mid+1;
else
e=mid;
}
o=0;
for (j=s;(j<=2*m)&(x1[dl[j]]==x2[k])&(y11[dl[j]]==y2[k]);j++)
if ((x2[dl[j]]!=x1[k])||(y2[dl[j]]!=y11[k]))
if ((o==0)||(quick(k,dl[j])<quick(k,o))) o=dl[j];
belong[o]=tot;
double u1,v1,u2,v2;
u1=x1[k]-x1[dl[i]];
v1=y11[k]-y11[dl[i]];
u2=x2[k]-x1[dl[i]];
v2=y2[k]-y11[dl[i]];
z+=(u1*v2-u2*v1)/2;
k=o;
all++;
xl[all]=k;
}
while (k!=dl[i]);
while ((z<0)&(all>0))
{
belong[xl[all]]=-1;
all--;
}
if (z<0) tot--;
}
for (i=1;i<=n;i++)
{
memset(coun,0,sizeof(coun));
for (j=1;j<=m*2;j++)
if ((belong[j]>0)&(meet(x[i],y[i],x[i]+1,100000,x1[j],y11[j],x2[j],y2[j])))
coun[belong[j]]++;
for (j=1;j<=n;j++)
if (coun[j]&1==1)
{
w[j]++;
incl[j][i]=1;
oo[j][i]=1;
linkk[i][j]=1;
}
}
for (i=1;i<=n;i++) p[i]=w[i];
tot=0;
for (i=1;i<=n;i++)
if (w[i]==1)
{
tot++;
xl[tot]=i;
}
i=1;
while (i<=tot)
{
for (k=1;k<=n;k++)
if (incl[xl[i]][k]==1) break;
who[xl[i]]=k;
for (j=1;j<=n;j++)
if (linkk[k][j]==1)
{
incl[j][k]=0;
w[j]--;
if (w[j]==1)
{
tot++;
xl[tot]=j;
}
}
i++;
}
for (i=1;i<=m*2;i++)
if ((belong[i]>0)&(belong[anti(i)]>0))
ans[who[belong[i]]][who[belong[anti(i)]]]=1;
for (i=1;i<=n;i++)
for (j=1;j<=m*2;j++)
if ((belong[j]==i)&(belong[anti(j)]==-1))
{
ok[i]=true;
break;
}
for (i=1;i<=n;i++)
{
tot=0;
for (j=1;j<=n;j++)
if (oo[j][i]!=0)
{
tot++;
dl[tot]=j;
}
if (tot>=2)
{
sort(dl+1,dl+tot+1,wwwww);
for (j=2;j<=tot;j++)
if (ok[dl[j]])
{
ans[who[dl[j]]][who[dl[j-1]]]=1;
ans[who[dl[j-1]]][who[dl[j]]]=1;
}
}
}
for (i=1;i<=n;i++)
{
k=0;
for (j=1;j<=n;j++)
if (ans[i][j]!=0) k++;
printf("%d",k);
for (j=1;j<=n;j++)
if (ans[i][j]!=0) printf(" %d",j);
cout << endl;
}
}



• 0
点赞
• 0
收藏
觉得还不错? 一键收藏
• 0
评论
02-19 347
02-09 699
01-15 855
02-03 83
06-18 331
08-08 331
08-09 219
08-08 584
08-12 213
08-07 409

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。