ZOJ 2589 Circles(平面图欧拉公式)
【题目链接】 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2589
【题目大意】
给出一些圆,问这些圆可以把平面分为几个部分。
【题解】
我们发现圆交图一定是个平面图,因此可以用平面图欧拉公式R=E-V+2
但是我们发现有些圆并不相交,因此每个图需要单独完全计算,
我们计算每个封闭图形的平面数,他们的和+1便是答案,
考虑单独的封闭图形有R=E-V+1,在下图中:
我们发现当蓝色的圆加入图中之后,他为平面增加的点数是4,增加的边数是8,
其中属于蓝色的圆弧的边数为4,其余四条增加的边源于红色和黄色圆弧上点的增加,
所以我们发现对于一个圆来说,它为平面贡献的边数为其与其余圆的交点数,
至于封闭平面图形点的计算,我们在搜索中用set来去重即可。
【代码】
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <vector>
#include <set>
using namespace std;
double eps=1e-8;
int sgn(double x) {
if(x<-eps)return -1;
if(x>eps)return 1;
return 0;
}
struct vec{
double x,y;
vec(double x=0,double y=0):x(x),y(y){}
vec operator + (vec v){return vec(x+v.x,y+v.y);}
vec operator - (vec v){return vec(x-v.x,y-v.y);}
vec operator * (double v){return vec(x*v,y*v);}
vec operator / (double v){return vec(x/v,y/v);}
bool operator < (const vec &rhs)const{
if(sgn(x-rhs.x)!=0)return x<rhs.x;
else if(sgn(y-rhs.y)!=0)return y<rhs.y;
else return false;
}
bool operator ==(const vec &rhs)const{
return sgn(x-rhs.x)==0&&sgn(y-rhs.y)==0;
}
double operator *(vec v){return x*v.x+y*v.y;}
double len(){return hypot(x,y);}
double len_sqr(){return x*x+y*y;}
double angle(){return atan2(y,x);}
//逆时针旋转
vec rotate(double c){return vec(x*cos(c)-y*sin(c),x*sin(c)+y*cos(c));}
vec trunc(double l){return (*this)*l/len();}
vec rot90(){return vec(-y,x);}
};
struct circle{
vec c;double r;
circle(vec c=vec(0,0),double r=0):c(c),r(r){}
vec point(const double &a)const{
return vec(c.x+cos(a)*r,c.y+sin(a)*r);
}
};
//圆圆相交
int circle_circle_intersection(circle a,circle b,vec &p1,vec &p2) {
double d=(a.c-b.c).len();
if(sgn(d)==0)return 0;
if(sgn(a.r+b.r-d)<0||sgn(fabs(a.r-b.r)-d)>0)return false;//相离|内含
double an=(b.c-a.c).angle();
double da=acos((a.r*a.r+d*d-b.r*b.r)/(2*a.r*d));
p1=a.point(an-da);
p2=a.point(an+da);
if(p1==p2)return 1;
else return 2;
}
const int N=60;
vector<circle> cir;
vector<int> G[N];
set<vec> dfs_save,set_p[N];
set<vec>::iterator it;
int v[N],E,T,n;
void dfs(int x){
v[x]=1;
for(it=set_p[x].begin();it!=set_p[x].end();it++)dfs_save.insert(*it);
E+=(int)set_p[x].size();
for(int i=0;i<G[x].size();i++)if(!v[G[x][i]])dfs(G[x][i]);
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n); cir.clear();
for(int i=0;i<n;i++)G[i].clear(),set_p[i].clear();
memset(v,0,sizeof(v));
for(int i=0;i<n;i++){
double x,y,r;
scanf("%lf%lf%lf",&x,&y,&r);
cir.push_back(circle(vec(x,y),r));
}
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++){
vec a,b;
int u=circle_circle_intersection(cir[i],cir[j],a,b);
if(u){
G[i].push_back(j); G[j].push_back(i);
set_p[i].insert(a); set_p[j].insert(a);
set_p[i].insert(b); set_p[j].insert(b);
}
}int ans=0;
for(int i=0;i<n;i++){
if(!v[i]){
dfs_save.clear(); E=0;
dfs(i); ans+=E-(int)dfs_save.size()+1;
}
}printf("%d\n",ans+1);
}return 0;
}
ZOJ 2589 Circles(平面图欧拉公式)的更多相关文章
- P7295-[USACO21JAN]Paint by Letters P【平面图欧拉公式】
正题 题目链接:https://www.luogu.com.cn/problem/P7295 题目大意 给出\(n*m\)的网格,每个格子上有字母,相同字母的四联通相邻格子为连通,每次询问一个子矩阵求 ...
- POJ--2284--That Nice Euler Circuit【平面图欧拉公式】
链接:id=2284">http://poj.org/problem?id=2284 题意:一个自己主动绘图的机器在纸上(无限大)绘图,笔尖从不离开纸,有n个指令,每一个指令是一个坐标 ...
- zoj 2589 Matrix Searching 二维线段树
题目链接 给一个n*n的矩阵, 给q个查询, 每次给出x1, y1, x2, y2, 求这个矩阵中的最小值. 代码基本上和上一题相同... #include<bits/stdc++.h> ...
- ACM计算几何题目推荐
//第一期 计算几何题的特点与做题要领: 1.大部分不会很难,少部分题目思路很巧妙 2.做计算几何题目,模板很重要,模板必须高度可靠. 3.要注意代码的组织,因为计算几何的题目很容易上两百行代码,里面 ...
- ZOJ 1608 Two Circles and a Rectangle
Give you two circles and a rectangle, your task is to judge wheather the two circles can be put into ...
- poj2284 That Nice Euler Circuit(欧拉公式)
题目链接:poj2284 That Nice Euler Circuit 欧拉公式:如果G是一个阶为n,边数为m且含有r个区域的连通平面图,则有恒等式:n-m+r=2. 欧拉公式的推广: 对于具有k( ...
- POJ2284 That Nice Euler Circuit (欧拉公式)(计算几何 线段相交问题)
That Nice Euler Circuit Time Limit: 3000MS M ...
- 【转载】图论 500题——主要为hdu/poj/zoj
转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并 ...
- UVa 10213 (欧拉公式+Java大数) How Many Pieces of Land ?
题意: 一块圆形土地,在圆周上选n个点,然后两两连线,问把这块土地分成多少块? 分析: 首先紫书上的公式是错的,不过根据书上提供的思路很容易稍加修改得到正确答案! 然后推公式吧,这里用到平面图的欧拉公 ...
随机推荐
- Optimal Milking(POJ2112+二分+Dinic)
题目链接:http://poj.org/problem?id=2112 题目: 题意:有k台挤奶机,c头奶牛,每台挤奶机每天最多生产m的奶,给你每个物品到其他物品的距离(除了物品到自己本省的距离为0外 ...
- 简易微信小程序签到功能
一.效果图 点击签到后 二.数据库 用一张数据表存用户签到的信息,每次用户签到都会往表中添加一条记录了用户id和签到日期的数据,如下图 三.后端 后端写两个接口,一个用于查询用户今日是否签到和签到记录 ...
- SQL SERVER 创建远程数据库链接 mysql oracle sqlserver
遇到的坑 在连接Oracle时,因为服务器为10g 32位版本,然后在本地安装了32为10g客户端,然后一直报错[7302.7303],后来下载了12c 64位版本,安装成功后,问题解决 原因:mss ...
- Ubuntu安装pip
首先打开终端 在终端输入:sudo apt-get install python-pip python-dev build-essential [+] 如果需要在Python3下安装pip,那么在py ...
- Deep Learning基础--26种神经网络激活函数可视化
在神经网络中,激活函数决定来自给定输入集的节点的输出,其中非线性激活函数允许网络复制复杂的非线性行为.正如绝大多数神经网络借助某种形式的梯度下降进行优化,激活函数需要是可微分(或者至少是几乎完全可微分 ...
- 2017多校第6场 HDU 6096 String AC自动机
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6096 题意:给了一些模式串,然后再给出一些文本串的不想交的前后缀,问文本串在模式串的出现次数. 解法: ...
- mybatis开启字段自动映射为java驼峰命名规则
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> & ...
- 对list对象进行排序
List<LjlSevOrdersVO> list = ljlSevOrdersService.findSevForOrders(ljlSevOrdersVO); //查出所有是自愿者的订 ...
- FineReport——巧妙实现类tab布局
在FR中,表达form支持局部刷新和tab布局,在报表中,不能做到这样,只能舍弃一些功能来做到类似的tab布局. 首先,在参数面板放一个文本控件temp,用作一个临时值,需要设置一个默认值,而切换是通 ...
- css设置div等标签背景半透明
三种方式: 1. background-color: transparent; 直接设置背景为透明 2.这种是子元素也会跟着变成半透明 /* 背景半透明,1为不透明 */ opacity: 0.5; ...