Description
省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏。
这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着道路走到
任意其他城市。现在小C已经占领了其中至少两个城市,小Q可以摧毁一个小C没占领的城市,同时摧毁所有连接这
个城市的道路。只要在摧毁这个城市之后能够找到某两个小C占领的城市u和v,使得从u出发沿着道路无论如何都不
能走到v,那么小Q就能赢下这一局游戏。
小Q和小C一共进行了q局游戏,每一局游戏会给出小C占领的城市集合S
你需要帮小Q数出有多少个城市在他摧毁之后能够让他赢下这一局游戏。
Input
第一行包含一个正整数T,表示测试数据的组数,
对于每组测试数据,
第一行是两个整数n和m,表示地图的城市数和道路数,
接下来m行,每行包含两个整数u和v~(1<=u
Output
对于每一局游戏,输出一行,包含一个整数,表示这一局游戏中有多少个城市在小Q摧毁之后能够让他赢下这一局游戏。
Sample Input
2
7 6
1 2
1 3
2 4
2 5
3 6
3 7
3
2 1 2
3 2 3 4
4 4 5 6 7
6 6
1 2
1 3
2 3
1 4
2 5
3 6
4
3 1 2 3
3 1 2 6
3 1 5 6
3 4 5 6
Sample Output
0
1
3
0
1
2
3
解题思路:
建出圆方树,答案就是虚树上圆点个数-询问端点个数。
#include<bits/stdc++.h>
#define ll long long
#define LD long double
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
if(c=='-')c=getchar(),f=-1;
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=100005;
int n,m,q[N];
LD x[N][2],y[N][2],Sec[N],val[N],p[N],X0,Y0,X1,Y1,L,x0;
inline bool cmp(int a,int b){return ((a>0)?x[a][0]:x[-a][1])<((b>0)?x[b][0]:x[-b][1]);}
struct line
{
int u;
line(int _u=0):u(_u){}
inline friend bool operator < (const line &a,const line &b)
{
if(a.u==b.u)return false;
LD ya=(y[a.u][0]-y[a.u][1])/(x[a.u][0]-x[a.u][1])*(x0-x[a.u][0])+y[a.u][0];
LD yb=(y[b.u][0]-y[b.u][1])/(x[b.u][0]-x[b.u][1])*(x0-x[b.u][0])+y[b.u][0];
return abs(ya)<abs(yb);
}
};set<line>S_up,S_down;
void solve()
{
n=getint(),m=0;
for(int i=1;i<=n;i++)
{
x[i][0]=getint(),y[i][0]=getint(),x[i][1]=getint(),y[i][1]=getint();
Sec[i]=sqrt((x[i][0]-x[i][1])*(x[i][0]-x[i][1])+(y[i][0]-y[i][1])*(y[i][0]-y[i][1]));
}
X0=getint(),Y0=getint(),X1=getint(),Y1=getint(),L=getint();
if(X0>X1)swap(X0,X1),swap(Y0,Y1);
LD dx=X1-X0,dy=Y1-Y0,len=sqrt(dx*dx+dy*dy),Sin=dy/len,Cos=dx/len;
for(int i=1;i<=n;i++)
{
x[i][0]-=X0,x[i][1]-=X0,y[i][0]-=Y0,y[i][1]-=Y0;
LD t1,t2,t3,t4;
t1=x[i][0]*Cos+y[i][0]*Sin,t2=y[i][0]*Cos-x[i][0]*Sin;
t3=x[i][1]*Cos+y[i][1]*Sin,t4=y[i][1]*Cos-x[i][1]*Sin;
x[i][0]=t1,y[i][0]=t2,x[i][1]=t3,y[i][1]=t4;
}
for(int i=1;i<=n;i++)
{
if(x[i][0]>x[i][1])swap(x[i][0],x[i][1]),swap(y[i][0],y[i][1]);
Sec[i]/=(x[i][1]-x[i][0]);
}
for(int i=1;i<=n;i++)q[++m]=i,q[++m]=-i;
sort(q+1,q+m+1,cmp);
for(int i=1;i<=m;i++)val[i]=0;
for(int i=1,u;i<=m;i++)
{
if(q[i]>0)
{
u=q[i];x0=p[i]=x[u][0];
if(!S_up.empty())val[i]+=Sec[S_up.begin()->u];
if(!S_down.empty())val[i]+=Sec[S_down.begin()->u];
((y[u][0]>0)?S_up:S_down).insert(line(u));
}
else
{
u=-q[i];x0=p[i]=x[u][1];
if(!S_up.empty())val[i]+=Sec[S_up.begin()->u];
if(!S_down.empty())val[i]+=Sec[S_down.begin()->u];
((y[u][0]>0)?S_up:S_down).erase(line(u));
}
}
LD res=0,ans=0,l=p[1]-L,r=p[1];int pl=1,pr=2;
while(pr<=m)
{
LD dl=p[pl]-l,dr=p[pr]-r;
if(dl>dr)res+=(val[pr]-val[pl])*dr,pr++,l+=dr,r+=dr;
else if(dl<dr)res+=(val[pr]-val[pl])*dl,pl++,l+=dl,r+=dl;
else res+=(val[pr]-val[pl])*dl,pl++,pr++,l+=dl,r+=dl;
ans=max(ans,res);
}
printf("%.15Lf\n",ans);
}
int main()
{
freopen("laser.in","r",stdin);
freopen("laser.out","w",stdout);
for(int T=getint();T;T--)solve();
return 0;
}