poj-3140
来源:互联网 发布:写作业软件下载 编辑:程序博客网 时间:2024/05/29 08:24
//10344K 391MS C++#include <cstdio>#include <cstring>#include <cmath>const long long MAX = 100005;long long adjacentListHead[MAX];long long studentTotalSum;struct Node{ long long studentNum;};long long Idx;struct ConnectedNode{ int curNodeId; int nextNodePos;};typedef struct ConnectedNode ConnectedNode;ConnectedNode adjacentNodes[1000005];typedef struct Node Node;Node nodes[MAX];long long DP[MAX];long long uNum;long long connectionNum;long long minDiffer = -1;inline long long MIN(long long A, long long B) { return A < B ? A: B;}void addInAdjacentList(int nodeId, int adjacentNodeId) { Idx++; adjacentNodes[Idx].curNodeId = adjacentNodeId; adjacentNodes[Idx].nextNodePos = adjacentListHead[nodeId]; adjacentListHead[nodeId] = Idx;}inline long long ABS(long long A) { return A > 0? A: -A;}void dfs(long long curNodeId, long long prevNodeId) { // visited[curNodeId] = 1; long long adjacentNodePos = adjacentListHead[curNodeId]; long long adjacentNodeId = adjacentNodes[adjacentNodePos].curNodeId; long long adjacentNum = 0; while(adjacentNodeId) { // prlong longf("A adjacentNodeId: %d curNodeId: %d prevNodeId: %d\n", adjacentNodeId, curNodeId, prevNodeId); if (adjacentNodeId != prevNodeId) { dfs(adjacentNodeId, curNodeId); adjacentNum++; DP[curNodeId] += DP[adjacentNodeId]; } adjacentNodePos = adjacentNodes[adjacentNodePos].nextNodePos; adjacentNodeId = adjacentNodes[adjacentNodePos].curNodeId; } DP[curNodeId] += nodes[curNodeId].studentNum; // prlong longf("%lld %d\n", DP[curNodeId], curNodeId); if (minDiffer == -1) { minDiffer = ABS(studentTotalSum - 2*DP[curNodeId]); } else { minDiffer = MIN(minDiffer, ABS(studentTotalSum - 2*DP[curNodeId])); }}long long caseId = 1;int main() { while(scanf("%lld %lld", &uNum, &connectionNum) != EOF) { if (!uNum && !connectionNum) { return 0; } Idx = 0; studentTotalSum = 0; minDiffer = -1; memset(DP, 0, sizeof(DP)); // memset(visited, 0, sizeof(visited)); memset(adjacentListHead, 0, sizeof(adjacentListHead)); memset(adjacentNodes, 0, sizeof(adjacentNodes)); for (long long i = 1; i <= uNum; i++) { scanf("%lld", &(nodes[i].studentNum)); studentTotalSum += nodes[i].studentNum; } for (long long i = 1; i <= connectionNum; i++) { int A, B; scanf("%d %d", &A, &B); addInAdjacentList(A, B); addInAdjacentList(B, A); } dfs(1, -1); printf("Case %lld: %lld\n", caseId, minDiffer); caseId++; }}
水题,虽然挂着树状DP的名头,不过是非常简单的运用,倒是因为数据值太大引起了不少RE 和 WA。
题目要求的其实说白了就是,给你一个无根树,然后选择树种中的一条边断开,使得形成的两个子树的权值和的差的绝对值最小。
因为是无根树,所以完全可以任选一个点作为根,而因为题目的输入没有给出两个点的父子关系,并且树的节点非常多,因此在保存该树的时候,要用图的邻接表来表示(好久没用,邻接表的预分配数组开小了,RE了一次),在题目输入的时候,就先累加得到整个树的权值和S, 然后,就是选择一个点作为root(直接选了1),
那么下面就是DP了,DP[i]表示以i为根的子树的权值和,那么很简单的,DP[i] = SUM{DP[i的子节点]}, 注意,因为用的是邻接表表示的树,因此,实际的遍历点i的所有子节点,是通过遍历与i邻接的所有节点实现的,但是在这些邻接的点中,会有一个点其实是i的父节点,这个要区分开,可以在dfs()中多加一个参数P,表示此次dfs的节点i,其父节点是P,这样在遍历i的邻接点时,可以直接将p跳过。
每次得到一个子树的权值和时(即DP[i]),就算一个 abs(S - 2*DP[i])(就是以i为根的子树权值和 与 剩下的点组成的子树的权值和的差的绝对值), 在每次的dfs中,保存最小的abs(S - 2*DP[i]);
最后输出该最小值即可。
0 0
- POJ 3140
- POJ 3140
- poj-3140
- poj 3140
- poj 1655树形dp && poj 3107 &&poj 2378 && poj 3140
- poj 3140 树形dp
- poj 3140 Contestants Division
- poj 3140 树型DP
- POJ--3140--Contestants Division
- poj 3140 Contestants Division
- poj 3140 Contestants Division
- poj 3140 简单dfs
- poj-3140-树形dp
- POJ 3140 树形dp
- POJ 3140 Contestants Division
- poj 3140(树形dp)
- POJ 3140 Contestants Division
- poj 3140 建树
- AFNetworking 2.0 使用
- vs2013 编译libiconv
- 路径与目录
- C/C++ IO操作
- 自适应网页设计
- poj-3140
- Android中ListView嵌套GridView的简单消息流UI(解决宽高问题)
- java web项目使用axis2
- update xml数据
- RAC修改了子网掩码报错CRS-5008
- php mvc nginx url重写(经验累计)
- Cocos2dx 3.2 横版过关游戏Brave学习笔记(六)
- 注册页面的各种判断(正则表达式)
- 总结所有的javascript验证方法大全