URAL - 1966 - Cycling Roads(并查集 + 判线段相交)
2014-11-03 01:47
323 查看
题意:n 个点,m 条边(1 ≤ m < n ≤ 200),问所有点是否连通(两条边相交,则该 4 点连通)。
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1966
——>>对于每条边,边上的两端点并入集合,枚举边与边,判断他们是否相交,是的话各点并入集合,最后看集合内元素的个数是否为n。。
#include <cstdio>
#include <cmath>
const int MAXN = 200 + 10;
const double EPS = 1e-8;
struct POINT
{
double x;
double y;
POINT(){}
POINT(double x, double y) : x(x), y(y){}
} p[MAXN];
int n, m;
int fa[MAXN], cnt[MAXN];
int u[MAXN], v[MAXN];
typedef POINT Vector;
Vector operator - (Vector A, Vector B)
{
return Vector(A.x - B.x, A.y - B.y);
}
int Dcmp(double x)
{
if (fabs(x) < EPS) return 0;
return x > 0 ? 1 : -1;
}
double Dot(Vector A, Vector B)
{
return A.x * B.x + A.y * B.y;
}
double Cross(Vector A, Vector B)
{
return A.x * B.y - A.y * B.x;
}
bool SegmentProperIntersection(POINT a1, POINT a2, POINT b1, POINT b2)
{
double c1 = Cross(a2 - a1, b1 - a1);
double c2 = Cross(a2 - a1, b2 - a1);
double c3 = Cross(b2 - b1, a1 - b1);
double c4 = Cross(b2 - b1, a2 - b1);
return Dcmp(c1) * Dcmp(c2) < 0 && Dcmp(c3) * Dcmp(c4) < 0;
}
bool OnSegment(POINT p, POINT a1, POINT a2)
{
return Dcmp(Cross(a1 - p, a2 - p)) == 0 && Dcmp(Dot(a1 - p, a2 - p)) < 0;
}
void Init()
{
for (int i = 1; i <= n; ++i)
{
fa[i] = i;
cnt[i] = 1;
}
}
int Find(int x)
{
return x == fa[x] ? x : (fa[x] = Find(fa[x]));
}
void Union(int x, int y)
{
int xroot = Find(x);
int yroot = Find(y);
if (xroot != yroot)
{
fa[yroot] = xroot;
cnt[xroot] += cnt[yroot];
}
}
void Read()
{
for (int i = 1; i <= n; ++i)
{
scanf("%lf%lf", &p[i].x, &p[i].y);
}
for (int i = 0; i < m; ++i)
{
scanf("%d%d", u + i, v + i);
Union(u[i], v[i]);
for (int j = 1; j <= n; ++j)
{
if (j != u[i] && j != v[i] && OnSegment(p[j], p[u[i]], p[v[i]]))
{
Union(j, u[i]);
}
}
}
}
void Merge()
{
for (int i = 0; i < m; ++i)
{
for (int j = i + 1; j < m; ++j)
{
if (SegmentProperIntersection(p[u[i]], p[v[i]], p[u[j]], p[v[j]]))
{
Union(u[i], u[j]);
}
}
}
}
void Output()
{
cnt[Find(1)] == n ? puts("YES") : puts("NO");
}
int main()
{
while (scanf("%d%d", &n, &m) == 2)
{
Init();
Read();
Merge();
Output();
}
return 0;
}
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1966
——>>对于每条边,边上的两端点并入集合,枚举边与边,判断他们是否相交,是的话各点并入集合,最后看集合内元素的个数是否为n。。
#include <cstdio>
#include <cmath>
const int MAXN = 200 + 10;
const double EPS = 1e-8;
struct POINT
{
double x;
double y;
POINT(){}
POINT(double x, double y) : x(x), y(y){}
} p[MAXN];
int n, m;
int fa[MAXN], cnt[MAXN];
int u[MAXN], v[MAXN];
typedef POINT Vector;
Vector operator - (Vector A, Vector B)
{
return Vector(A.x - B.x, A.y - B.y);
}
int Dcmp(double x)
{
if (fabs(x) < EPS) return 0;
return x > 0 ? 1 : -1;
}
double Dot(Vector A, Vector B)
{
return A.x * B.x + A.y * B.y;
}
double Cross(Vector A, Vector B)
{
return A.x * B.y - A.y * B.x;
}
bool SegmentProperIntersection(POINT a1, POINT a2, POINT b1, POINT b2)
{
double c1 = Cross(a2 - a1, b1 - a1);
double c2 = Cross(a2 - a1, b2 - a1);
double c3 = Cross(b2 - b1, a1 - b1);
double c4 = Cross(b2 - b1, a2 - b1);
return Dcmp(c1) * Dcmp(c2) < 0 && Dcmp(c3) * Dcmp(c4) < 0;
}
bool OnSegment(POINT p, POINT a1, POINT a2)
{
return Dcmp(Cross(a1 - p, a2 - p)) == 0 && Dcmp(Dot(a1 - p, a2 - p)) < 0;
}
void Init()
{
for (int i = 1; i <= n; ++i)
{
fa[i] = i;
cnt[i] = 1;
}
}
int Find(int x)
{
return x == fa[x] ? x : (fa[x] = Find(fa[x]));
}
void Union(int x, int y)
{
int xroot = Find(x);
int yroot = Find(y);
if (xroot != yroot)
{
fa[yroot] = xroot;
cnt[xroot] += cnt[yroot];
}
}
void Read()
{
for (int i = 1; i <= n; ++i)
{
scanf("%lf%lf", &p[i].x, &p[i].y);
}
for (int i = 0; i < m; ++i)
{
scanf("%d%d", u + i, v + i);
Union(u[i], v[i]);
for (int j = 1; j <= n; ++j)
{
if (j != u[i] && j != v[i] && OnSegment(p[j], p[u[i]], p[v[i]]))
{
Union(j, u[i]);
}
}
}
}
void Merge()
{
for (int i = 0; i < m; ++i)
{
for (int j = i + 1; j < m; ++j)
{
if (SegmentProperIntersection(p[u[i]], p[v[i]], p[u[j]], p[v[j]]))
{
Union(u[i], u[j]);
}
}
}
}
void Output()
{
cnt[Find(1)] == n ? puts("YES") : puts("NO");
}
int main()
{
while (scanf("%d%d", &n, &m) == 2)
{
Init();
Read();
Merge();
Output();
}
return 0;
}
相关文章推荐
- URAL 1966 Cycling Roads 点在线段上、线段是否相交、并查集
- Cycling Roads URAL 1966 线段相交 + 并查集
- URAL - 1966 - Cycling Roads(并检查集合 + 判刑线相交)
- hdu 1558 Segment set(线段相交+并查集)
- hdu 1558 并查集+线段相交
- poj1127 Jack Straws(线段相交+并查集)
- hdu 1558(线段相交+并查集)
- hdu 1558 判断线段相交 + 并查集
- TOJ 1840 POJ 1127 HDU 1102 Jack Straws / 线段相交 + 并查集
- HDU 1158 Segment set(线段相交 并查集)
- HDU-1558,Segment set,并查集+线段相交模拟
- ACM1558两线段相交判断和并查集
- poj1127 Jack Straws 线段相交+并查集
- 【计算几何初步-线段相交+并查集】【HDU1558】Segment set
- hdu 1558(线段相交+并查集)
- HDU 1558 Segment set(线段相交+并查集)
- 第五次个人赛D题 Segment set 判断线段相交+并查集
- hdu1558 Segment set (判断线段相交+并查集)
- hdu 1558 Segment set 线段相交+并查集
- hdu 1558 Segment set 并查集 叉积判断线段是否相交