UVA 10319 - Manhattan(2-SET)

来源:互联网 发布:跳跃网络次元大作战 编辑:程序博客网 时间:2024/06/16 07:22

UVA 10319 - Manhattan

题目链接

题意:一个城市,有南北和东西街道,每种街道都是单行道,现在给定几个起点和终点,要求起点和终点必须最多转一次弯可以到达,问是否可以满足所有的起点终点

思路:2-set,对于东西,南北街道,向西(北)为false,向东(南)为true,对于每个起点终点,肯定是走坐标对应的那4条街道,表示出来是(s1 & a2) | (s2 & a1),可以转化成(s1 | s2) & (s1 | a1) & (a2 | v2) & (a2 | a1)对应2-set4条边,注意如果横坐标或纵坐标相同,只要建一条边(s, s)即可,这样建图,进行2-set判定即可

代码:

#include <cstdio>#include <cstring>#include <cstdlib>#include <vector>#include <algorithm>using namespace std;const int MAXNODE = 2005;struct TwoSet {int n;vector<int> g[MAXNODE * 2];bool mark[MAXNODE * 2];int S[MAXNODE * 2], sn;void init(int tot) {n = tot * 2;for (int i = 0; i < n; i += 2) {g[i].clear();g[i^1].clear();}memset(mark, false, sizeof(mark));}void add_Edge(int u, int uval, int v, int vval) {u = u * 2 + uval;v = v * 2 + vval;g[u^1].push_back(v);g[v^1].push_back(u);}bool dfs(int u) {if (mark[u^1]) return false;if (mark[u]) return true;mark[u] = true;S[sn++] = u;for (int i = 0; i < g[u].size(); i++) {int v = g[u][i];if (!dfs(v)) return false;}return true;}bool solve() {for (int i = 0; i < n; i += 2) {if (!mark[i] && !mark[i + 1]) {sn = 0;if (!dfs(i)){for (int j = 0; j < sn; j++)mark[S[j]] = false;sn = 0;if (!dfs(i + 1)) return false;}}}return true;}} gao;int n, S, A, m;int main() {scanf("%d", &n);while (n--) {scanf("%d%d%d", &S, &A, &m);gao.init(S + A);int s1, a1, s2, a2;while (m--) {scanf("%d%d%d%d", &s1, &a1, &s2, &a2);s1--; a1--; s2--; a2--;if (s1 == s2 && a1 == a2) continue;a1 += S;a2 += S;if (s1 == s2) gao.add_Edge(s1, (a1 < a2), s2, (a1 < a2));else if (a1 == a2) gao.add_Edge(a1, (s1 < s2), a2, (s1 < s2));else {gao.add_Edge(s1, (a1 < a2), s2, (a1 < a2));gao.add_Edge(s1, (a1 < a2), a1, (s1 < s2));gao.add_Edge(a2, (s1 < s2), s2, (a1 < a2));gao.add_Edge(a2, (s1 < s2), a1, (s1 < s2));}}printf("%s\n", gao.solve() ? "Yes" : "No");}return 0;}


1 0
原创粉丝点击