【BAPC 2017】Hoarse Horses【欧拉平面图公式】

前言

如果你对这篇文章可感兴趣,可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接。

题意

给出 n n n 条线段,求平面中一共有多少个闭合区域。保证不存在三条线段相交与一点,并且线段都是规范相交,即不存在相交点在线段端点。 ( 1 ≤ n ≤ 1000 ) (1\leq n\leq 1000) (1n1000)

题目链接: l i n k link link


思路

此题是一个公式题,因此直接上公式。

基本术语
  • 平面图:不存在边交叉的二维平面上的图
  • 连通平面图:平面图上的图形相互连通,即可以仅依靠图中的边从任意一个节点到达另外一个节点
欧拉平面图公式
  • 基本公式(针对连通平面图)
    • V − E + F = 2 V-E+F=2 VE+F=2,其中 V V V 为点数, E E E 为边数, F F F 为面数(即闭合区域)
    • 此处的 F F F 包括最外层的面
    • 此公式可用数学归纳法证明,证明过程简单易懂,读者可自行查阅
  • 广义公式(针对平面图)
    • V − E + F = 1 + C V-E+F=1+C VE+F=1+C,其中 C C C 为平面图中的连通块个数
    • 此公式可根据基本公式推出,推导过程较为简单,读者可自行思考
本题做法

由于本题仅给出了线段,并不满足平面图的限制,因此我们可以将线段的交点当作一个新的点,将原来的图形转化成平面图,转化过程如下图所示。(题解 l i n k link link
在这里插入图片描述
因此在转化后的图中,点数变为 ( 2 ∗ n + i n t e r ) (2*n+inter) (2n+inter),边数变为 ( n + 2 ∗ i n t e r ) (n+2*inter) (n+2inter),其中 i n t e r inter inter 为直线交点个数, c o m p comp comp 为连通块个数,即最终答案如下:(本题忽略最外层的点)
F = C + E − V = c o m p + ( n + 2 ∗ i n t e r ) − ( 2 ∗ n + i n t e r ) = c o m p + i n t e r − n F=C+E-V=comp+(n+2*inter)-(2*n+inter)=comp+inter-n F=C+EV=comp+(n+2inter)(2n+inter)=comp+intern


代码

#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof a);
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define per(i,a,b) for(int i = a; i >= b; i--)
typedef long long ll;
const int N = 1e4+100;
using namespace std;

int n, inter, vis[N], comp;
vector<int> G[N];

inline int sgn(ll x) { return x >= 0 ? x > 0 : -1;}

struct Point{
	ll x,y;
	Point() {}
	Point(ll _x, ll _y) : x(_x), y(_y) {}
	Point operator-(Point p) { return {x-p.x, y-p.y}; }
	ll det(Point p) { return x*p.y-y*p.x; } //叉积
	ll dot(Point p) { return x*p.x+y*p.y; }	//点积
}P1[N],P2[N];

struct Line{
	Point s,e;
	Line() {}
	Line(Point _s, Point _e){
		s = _s;
		e = _e;
	}
	int segcrosseg(Line v){
		int d1 = sgn((e-s).det(v.s-s));
		int d2 = sgn((e-s).det(v.e-s));
		int d3 = sgn((v.e-v.s).det(s-v.s));
		int d4 = sgn((v.e-v.s).det(e-v.s));
		if(((d1^d2) == -2) && (d3^d4) == -2) return 2;
		return (d1==0 && sgn((v.s-s).dot(v.s-e)) <= 0) ||
			   (d2==0 && sgn((v.e-s).dot(v.e-e)) <= 0) ||
			   (d3==0 && sgn((s-v.s).dot(s-v.e)) <= 0) ||
			   (d4==0 && sgn((e-v.s).dot(e-v.e)) <= 0);
	}
};

void dfs(int x){
	if(vis[x]) return;
	vis[x] = 1;
	for(auto y:G[x]) dfs(y);
}

int main()
{
	scanf("%d",&n);
	rep(i,1,n) scanf("%lld%lld%lld%lld",&P1[i].x,&P1[i].y,&P2[i].x,&P2[i].y);
	rep(i,1,n){
		Line l1 = {P1[i], P2[i]};
		rep(j,i+1,n){
			Line l2 = {P1[j], P2[j]};
			if(l1.segcrosseg(l2) != 0){
				G[i].push_back(j);
				G[j].push_back(i);
				inter++;
			}
		}
	}
	rep(i,1,n)
		if(!vis[i]){
			comp++;
			dfs(i);
		}
	printf("%d\n", inter+comp-n);
	return 0;
}
BAPC(Bayesian Age-Period-Cohort)预测模型是一种统计模型,它用于分析和预测在考虑年龄、时期和队列效应影响下的数据。这种模型特别适用于人口学、流行病学和市场营销等领域,其中数据受到这些时间相关因素的影响。BAPC模型通常通过贝叶斯方法来实现,利用贝叶斯推断来估计模型参数。 在R语言中,可以使用不同的包来实现BAPC模型,比如`apc`或`BAMP`。但是,R中并没有一个专门叫做BAPC的包。以下是一个简单的例子,演示如何使用`apc`包进行年龄-时期-队列模型的分析。请注意,这里仅提供了代码的一个基本框架,你可能需要根据自己的具体数据和研究目的进行适当的调整。 ```R # 安装并加载apc包 install.packages("apc") library(apc) # 假设你有一个名为data的数据框,其中包含以下列: # year: 年份 # age: 年龄 # count: 每一年每个年龄组的计数数据 # age.group: 年龄分组变量 # 使用apc包中的函数来拟合模型 # apc_fit 是模型拟合对象 apc_fit <- apc模型拟合函数(data$year, data$age, data$count) # 查看模型结果 summary(apc_fit) # 进行预测 # predict函数中的newdata需要包含你想要预测的年份、年龄和队列信息 predictions <- predict(apc_fit, newdata=你的新数据框) # 打印预测结果 print(predictions) ``` 请记住,上述代码仅为示例,并不代表实际可用的代码。在实际应用中,需要根据数据的具体情况和分析需求来选择和调整合适的统计模型和分析方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gene_INNOCENT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值