hdu 5438 Ponds(线段树+dfs)
来源:互联网 发布:mac脚本编辑器 用途 编辑:程序博客网 时间:2024/05/17 00:09
题意:
有n个点,m条边,每个点都有权值。
然后开始删除点,删点规则是如果这个点连接其他点的数量小于2,那么这个点可以删除。
如果删除了某些点产生了其他可删除的点也将其删除。
直到删除到不能为止。问最后剩余的联通块中,点的数量是奇数的联通块中的点的权值和是多少。
解析:
先算出所有点的度数,然后把这些度数存入线段树中,每次询问线段树找到等于最小的度数的节点,把和该最小度数的节点相连的所有节点的度数-1,直到不能再删除为止。
线段树的作用就是加快查询最小度数的速度,以及加快查询等于最小度数节点的速度。
然后对剩下的节点进行dfs,找到奇数的联通块,把其权值加到答案中。
PS:看了题解,其实这题是拓扑排序,但是线段树做多了,看什么都像线段树了……
#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#define ls (o<<1)#define rs (o<<1|1)#define lson ls, L, M#define rson rs, M+1, R#define MID (L + R) >> 1using namespace std;typedef long long ll;const int INF = 0x3f3f3f3f;const int N = 1e4 + 10;int n, m;vector<int> G[N];ll a[N], minv[N << 2];int deg[N];bool vis[N];void init() { memset(vis, false, sizeof(vis)); memset(deg, 0, sizeof(deg)); for(int i = 1; i <= n; i++) G[i].clear();}inline void addEdge(int u, int v) { G[u].push_back(v);}inline void pushUp(int o) { minv[o] = min(minv[ls], minv[rs]);}void build(int o, int L, int R) { if(L == R) { minv[o] = deg[L]; return ; } int M = MID; build(lson); build(rson); pushUp(o);}int query(int o, int L, int R, int val) { if(L == R) { minv[o] = INF; return L; } int M = MID, ret = 0; if(val == minv[ls]) ret = query(lson, val); else ret = query(rson, val); pushUp(o); return ret;}void remove(int o, int L, int R, int pos) { if(L == R) { minv[o]--; if(minv[o] < 0) minv[o] = INF; return ; } int M = MID; if(pos <= M) remove(lson, pos); else remove(rson, pos); pushUp(o);}void dfs(int u, ll &sum, int &tot) { tot++; sum += a[u]; for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(vis[v]) continue; vis[v] = true; dfs(v, sum, tot); }}ll cal() { int tot; ll sum, ret = 0; for(int i = 1; i <= n; i++) { if(vis[i]) continue; tot = sum = 0; vis[i] = true; dfs(i, sum, tot); if(tot & 1) ret += sum; } return ret;}int main() { int u, v; int T; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); init(); for(int i = 1; i <= n; i++) { scanf("%lld", &a[i]); } for(int i = 1; i <= m; i++) { scanf("%d%d", &u, &v); deg[u]++, deg[v]++; addEdge(u, v); addEdge(v, u); } build(1, 1, n); while(minv[1] <= 1) { u = query(1, 1, n, minv[1]); vis[u] = true; for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(vis[v]) continue; remove(1, 1, n, v); } } printf("%lld\n", cal()); } return 0;}
0 0
- hdu 5438 Ponds(线段树+dfs)
- hdu 5438 Ponds DFS
- hdu 5438 Ponds(拓扑应用、DFS)
- HDU 5438 Ponds(拓扑排序 + DFS)
- HDU 5438 Ponds(拓扑排序+dfs)
- hdu 5438 Ponds(toposort+DFS)
- HDU 5438 Ponds dfs模拟
- HDU---5438-Ponds(DFS)(2015 Changchun)
- HDU 5438 Ponds (DFS + 并查集)
- HDU 5438 --Ponds【拓扑排序 && DFS】
- hdu 5438 Ponds(拓扑排序+dfs)
- hdu 5438 Ponds 拓扑序+简单dfs
- HDU 5437 Ponds(DFS)
- HDU 5438 Ponds (搜索)
- HDU 5438 Ponds (拓扑排序+DFS)2015 ACM/ICPC Asia Regional Changchun Online
- hdu 5438 Ponds 2015长春网络赛 图论 dfs bfs
- HDU 5438 Ponds (拓扑排序应用+DFS)
- HDU 5438 Ponds 拓扑序+并查集/DFS
- Python:函数参数传递:传值?引用?
- Java语言语法2
- 一步一步学算法-堆排序
- nyoj 38 布线问题(kruskal 最小生成树)
- 创建自己的Sprite子类时需要做哪些工作?
- hdu 5438 Ponds(线段树+dfs)
- 浏览器解析过程
- 二叉树的创建和遍历
- HDU 5233 杂题
- JSP之POST与GET的区别
- 排序算法 golang 实现
- CCF-2015-9-13-04
- hdu 5444 Elven Postman(模拟)
- C语言strstr()函数常用示例详解[求一个字符串在另一个字符串中出现的次数]