[HDU 5354] Bipartite Graph
来源:互联网 发布:nginx转发配置 编辑:程序博客网 时间:2024/06/05 10:24
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5354
题意: 给出n个点m条边的无向图, 要你求出哪些点满足在原图中删掉该点后是一个二分图, 输出一个01序列, 1表示这个点被删后是个二分图。
思路:考虑用黑白染色来判断二分图。 使用分治的思想, 用并查集维护每个点的颜色。对于一个区间[l, r], 所有两端点都不在该区间内的边, 无论删掉该区间的任一个点这些边都将留在图中, 用这些边进行黑白染色, 如果出现冲突则[l, r]中的点答案都是0, 不用再递归子区间。 否则, 保留当前并查集的样子, 继续递归左右子区间, 这些边也因为已经考虑过不用再考虑了, 直到l与r相等时这个点答案才是1。 记得每次递归回来要把并查集回溯到原本的状态。 为了方便操作, 并查集不要路径压缩, 为了防止超时还要按秩合并。
PS:注意将两个并查集合并时, 根据原本的染色情况, 有一个集合可能要打上反转标记。
#include <queue>#include <cstdio>#include <cstdlib>#include <algorithm>#define ls (x << 1)#define rs (x << 1 | 1)#define mid ((l + r) >> 1)const int N = (int)1e5 + 10;const int M = (int)2e6 + 10;using namespace std;int n, m;int fa[N], sz[N], bj[N], ans[N];vector<pair<int, int> > edge[N << 2];int* stk[M]; int top, val[M];int modf(int *x, int y){ stk[++ top] = x; val[top] = *x; return (*x) = y;}void recall(int aim){ while (top != aim) {(*stk[top]) = val[top]; top --;}}pair<int, int > find(int x){ int val = 0; while (fa[x] != x) val ^= 1 ^ bj[x], x = fa[x]; return make_pair(x, val ^ bj[x]);}void unnion(int x, int y, int z){ if (sz[x] < sz[y]) swap(x, y); modf(&fa[y], x); modf(&sz[x], sz[x] + sz[y]); modf(&bj[y], bj[y] ^ z);}bool in(int x, int l, int r){ return l <= x && x <= r;}void solve(int, int, int);void work(int, int, int, vector<pair<int, int> > &);void solve(int l, int r, int x){ if (l == r) {ans[l] = 1; return;} vector<pair<int, int> > ().swap(edge[ls]); vector<pair<int, int> > ().swap(edge[rs]); vector<pair<int, int> > tmp[2]; for (int j = 0; j < edge[x].size(); j ++){ int u = edge[x][j].first, v = edge[x][j].second; if (in(u, l, mid) || in(v, l, mid)) edge[ls].push_back(edge[x][j]); else tmp[0].push_back(edge[x][j]); if (in(u, mid + 1, r) || in(v, mid + 1, r)) edge[rs].push_back(edge[x][j]); else tmp[1].push_back(edge[x][j]); } work(l, mid, ls, tmp[0]); work(mid + 1, r, rs, tmp[1]);}void work(int l, int r, int x, vector<pair<int, int > > & tmp){ int _top = top; bool flag = 0; for (int j = 0; j < tmp.size(); j ++){ int u = tmp[j].first, v = tmp[j].second; pair<int, int > r1 = find(u), r2 = find(v); if (r1.first == r2.first){ if (r1.second == r2.second) {flag = 1; break;} } else unnion(r1.first, r2.first, r1.second != r2.second); } if (flag){ for (int i = l; i <= r; i ++) ans[i] = 0; } else solve(l, r, x); recall(_top);}int main(){ int T; for (scanf("%d", &T); T --; ){ scanf("%d %d", &n, &m); for (int i = 1; i <= n; i ++) fa[i] = i, sz[i] = 1, bj[i] = 0; vector<pair<int, int> > ().swap(edge[1]); for (int i = 1, u, v; i <= m; i ++){ scanf("%d %d", &u, &v); edge[1].push_back(make_pair(u, v)); } solve(1, n, 1); for (int i = 1; i <= n; i ++) printf("%d", ans[i]); puts(""); } return 0;}
阅读全文
0 0
- [HDU 5354] Bipartite Graph
- hdu 5313 Bipartite Graph
- hdu-5313 Bipartite Graph
- hdu 5313 Bipartite Graph
- HDU 5313 Bipartite Graph
- 【染色】 HDU 5313 Bipartite Graph
- HDU 5354 Bipartite Graph[cdq+并查集]
- 【hdu 5354】Bipartite Graph【分治 并查集】
- 【hdu】5354 Bipartite Graph【cdq分治+并查集】
- HDU 5354 Bipartite Graph 分治,并查集
- hdu 5313 Bipartite Graph 贪心+bfs染色
- 【HDU】5313 Bipartite Graph【二分图+背包】
- HDU 5313 Bipartite Graph(bitset + DP)
- Bipartite Graph
- [HDU 5313] Bipartite Graph 二分图染色+分组背包
- HDU 5313 BestCoder 1st Anniversary ($) 1004 Bipartite Graph
- hdu 5313 Bipartite Graph 完全二分图 深搜 bitset应用
- hdu 5313 Bipartite Graph(二分图染色+dp+bitset优化)
- 大数据学习、一
- ActiveMQ的集群方案对比及部署
- SpringBoot16-springboot的Web开发-Spring Boot的Thymeleaf支持
- [jzoj5236]【NOIP2017模拟8.7A组】利普希茨
- [双连通分量]LA5135 Mining your own business
- [HDU 5354] Bipartite Graph
- Hadoop学习(一)
- D
- [LeetCode]404. Sum of Left Leaves 树的典型题目
- POJ1789 Truck History
- 笔记11 《C++ 大学教程》
- 详解linux下编译安装配置php5.6.30过程
- Linux学习笔记01:文件管理
- 慕课网学习Java入门第二季笔记