Timus Online Judge 1966 Cycling Roads
来源:互联网 发布:淘宝宝贝视频制作 编辑:程序博客网 时间:2024/06/08 15:12
再一次对timus感到无力,这道题目是放在Graph Theory Problems里,却感觉和Graph Theory没有毛关系。明明是个计算几何嘛。
题目大意:Vova在深圳骑自行车逛公园,公园里有N处景点,给出N个景点的坐标,然后再给出M条为线段的边。若两条线段有公共点,那么这两条线段的四个端点中的任意一个都能到达其余三个。问Vova是否能从一个点出发,到达其余所有的景点。N和M的最大值都是200,每个景点的坐标的x和y的绝对值是小于等于30000的。
当看到这道题目的时候,也许会有很多人会想到用某种生成树的算法来解决,确实是这样的,假如所有点都在一棵生成树上,那么答案就是“YES”。所以,我们可以直接用并查集来维护,当所有的点都在一个集合内的时候我们就输出“YES”,否则答案就“NO”。我们可以将每条边的两个端点所在的集合先给合并,然后判断两条线段是否相交,若相交,就把两条线段所在的集合合并成一个集合。还有就是得考虑出现单点的情况,若某一个点在某一条线段上,我们就要合并这个点所在集合和这条线段所在的集合。最后判断一下总共有多少个集合就可以了。
其中, 判断线段相交用叉积,我想这个没什么好说的吧,需要注意的是坐标范围是-30000~30000,那么计算叉积的时候中间爆long long的情况,注意处理一下就可以了,反正我是在这里WA两次。
这段代码我调试了很久,原因是把main写成了mian,编译一直不能通过,报了一个看不懂的error,感到莫名其妙的,还以为是自己的编译器哪里文件被删掉了,还找别人帮我编译,实在是羞愧,还好吃饭的时候在手机上看代码看到了这个“mian”!!!
Show me the code!
#include <iostream>#include <vector>#define ll long long#define pll pair<ll, ll>#define pii pair<int, int>#define x first#define y secondusing namespace std;vector<pii> vec(201), edge;vector<int> fa(201);ll turn(ll a) {//因为叉积的结果只需要正负,所以,为了避免报long long,这里需要转换一下 if (a == 0) return 0; return a > 0 ? 1 : -1;}ll CrossProduct(pll a, pll b, pll c) {//判断点C在线段ab的左边还是右边 pll ab(b.x - a.x, b.y - a.y), ac(c.x - a.x, c.y - a.y); return turn(ab.x * ac.y - ab.y * ac.x);//abc三点共线是结果为0,c在ab左边的时候结果小于0,否则大于0}bool is_intersection(pll a, pll b, pll c, pll d) {//判断线段ab和cd是否有公共点 ll res_ab = CrossProduct(a, b, c) * CrossProduct(a, b, d); ll res_cd = CrossProduct(c, d, a) * CrossProduct(c, d, b); return res_ab < 0 && res_cd < 0;}int find(int x) { return fa[x] = fa[x] == x ? x : find(fa[x]);}void unite(int x, int y) { int fx = find(x), fy = find(y); fa[fy] = fx;}bool solve(int N) { for (int i = 1; i <= N; ++i) fa[i] = i; for (int i = 0; i < edge.size(); ++i) { unite(edge[i].x, edge[i].y);//合并同一线段的两个端点所在的集合 for (int j = i + 1; j < edge.size(); ++j) { unite(edge[j].x, edge[j].y);//合并同一线段的两个端点所在的集合 if (is_intersection(vec[edge[i].x], vec[edge[i].y], vec[edge[j].x], vec[edge[j].y])) {//若两条线段有公共点,那么就合并两条线段所在的集合 unite(edge[i].x, edge[j].x); } } } for (int i = 0; i < edge.size(); ++i) { for (int j = 1; j <= N; ++j) { pll a = vec[edge[i].x], b = vec[edge[i].y], c = vec[j]; int minx = min(a.x, b.x), maxx = max(a.x, b.x), miny = min(a.y, b.y), maxy = max(a.y, b.y); if (CrossProduct(a, b, c) == 0 && minx <= c.x && c.x <= maxx && miny <= c.y && c.y <= maxy) {//判断单点是否在这条线段上,若是,则合并单点所在的结合和这条线段所在集合 unite(edge[i].x, j); } } } int f1 = find(1); for (int i = 2; i <= N; ++i) {//计算集合的个数 if (find(i) != f1) return false; } return true;}int main() { int N, M; cin >> N >> M; for (int i = 1; i <= N; ++i) cin >> vec[i].x >> vec[i].y; for (int i = 0; i < M; ++i) { int u, v; cin >> u >> v; edge.push_back(pll(u, v)); } cout << (solve(N) ? "YES" : "NO") << endl; return 0;}
- Timus Online Judge 1966 Cycling Roads
- Timus Online Judge 哥德巴赫猜想
- Timus Online Judge 1033 Labyrinth
- Timus Online Judge:1225. Flags
- Timus Online Judge:1119. Metro
- 1350. Canteen Timus Online Judge
- Timus Online Judge 1658 Sum of Digits
- Timus Online Judge 1982 Electrification Plan
- Timus Online Judge 1742 Team building
- Timus Online Judge 2045 Richness of words
- Timus Online Judge 1651 Shortest Subchain
- Timus Online Judge 1045 Funny Game
- Timus Online Judge:1040. Airline Company
- Timus Online Judge:1820. Ural Steaks
- Timus Online Judge:1100. Final Standings
- 【Timus Online Judge 1132】 Square Root
- Timus Online Judge初级题目:1014. Product of Digits
- Timus Online Judge 1057. Amount of Degrees(数位dp)
- html5基础知识第四章其他标签
- 侧滑菜单1
- 4412裸机程序之点亮LED
- Spring4之Hello World
- Spark修炼之道(基础篇)——Linux大数据开发基础:第三节:用户和组
- Timus Online Judge 1966 Cycling Roads
- 装饰器模式-JAVA
- poj3468(线段树||树状数组)
- Head First Java勘误
- Unity Sharder帧动画
- 软件使用技巧2:EXCEL工作表保护密码的撤销
- 被驱动表 拼接列无法走索引
- HDU 2222 AC自动机
- cropper本地预览 裁剪,上传到服务器