POJ3687 球的标签(拓扑排序+优先队列)
来源:互联网 发布:算法设计举例 编辑:程序博客网 时间:2024/05/29 13:54
给定N个球,这些球的编号分别是1-N中的某个数字,它们的重量也分别是1-N中的某个数字,任意两个球的编号和重量不相等。
给定一些类似a<b的约束,表示编号为a的球比编号为b的球轻。要求符合约束条件的各个球的重量。若答案有多种,则输出的答案必须让编号为1的球重量尽量轻,接着是编号为2的球重量尽量轻,一直到编号为N的球尽量轻。
这道题是一个拓扑排序问题,把每个编号的球看成一个点,把约束看成点之间的边,构造出一个有向图进行拓扑排序。但由于题目要求输出的答案必须是编号小的球重量尽量轻,因此如果直接拓扑排序,则得到的答案不满足条件。解决的方法是改变每条边的方向,并且使用优先队列来存放入度为0的点,优先队列的队头是入度为0的点中编号最大的,这样的反向拓扑得到的排列刚好是题目要求答案的反向排列。
#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int N = 205;const int M = 40005;struct Edge{int pos;int next;};Edge edge[M];bool vis[N][N];int cur;int neigh[N];int n, m;int indegree[N];int pq[N], pqsize;int ans[N], k;void init(){pqsize = 0;for (int i = 1; i <= n; ++i) neigh[i] = -1;for (int i = 1; i <= n; ++i) indegree[i] = 0;for (int i = 1; i <= n; ++i){for (int j = 1; j <= n; ++j){vis[i][j] = false;}}cur = 0;}void upward(int pos){if (pos == 1) return;if (pq[pos] > pq[pos >> 1]){swap(pq[pos], pq[pos >> 1]);upward(pos >> 1);}}void downward(int pos) { if ((pos << 1) + 1 <= pqsize) { if (pq[pos << 1] > pq[(pos << 1) + 1] && pq[pos << 1] > pq[pos]) { swap(pq[pos << 1], pq[pos]); downward(pos << 1); } else if (pq[pos << 1] < pq[(pos << 1) + 1] && pq[(pos << 1) + 1] > pq[pos]) { swap(pq[(pos << 1) + 1], pq[pos]); downward((pos << 1) + 1); } } else if ((pos << 1) <= pqsize){ if (pq[pos << 1] > pq[pos]) { swap(pq[pos << 1], pq[pos]); downward(pos << 1); } } } void enque(int val){pq[++pqsize] = val;upward(pqsize);}int deque(){int ret = pq[1];pq[1] = pq[pqsize--];downward(1);return ret;}int main(){int T;int beg, end, t;scanf("%d", &T);while (T--){scanf("%d%d", &n, &m);init();for (int i = 0; i < m; ++i){scanf("%d%d", &end, &beg);if (vis[beg][end]) continue;vis[beg][end] = true;edge[cur].pos = end;edge[cur].next = neigh[beg];neigh[beg] = cur;++cur;++indegree[end];}for (int i = 1; i <= n; ++i){if (indegree[i] == 0) enque(i);}k = n;while (pqsize > 0){t = deque();ans[t] = k--;int e = neigh[t];while (e != -1){--indegree[edge[e].pos];if (indegree[edge[e].pos] == 0) enque(edge[e].pos);e = edge[e].next;}}if (k == 0){for (int i = 1; i < n; ++i) printf("%d ", ans[i]);printf("%d\n", ans[n]);}else printf("-1\n");}return 0;}
- POJ3687 球的标签(拓扑排序+优先队列)
- [poj3687]拓扑排序的应用
- POJ3687 Labeling Balls(拓扑排序的应用)
- POJ3687 Labeling Balls (拓扑排序)经典
- poj3687 图论 拓扑排序
- POJ3687-反向拓扑排序
- poj3687 拓扑排序
- 拓扑排序变形poj3687
- poj3687【拓扑排序】
- POJ3687拓扑排序+贪心
- 拓扑排序+优先队列
- 拓扑排序+优先队列
- poj3687~拓扑排序(附上拓扑排序详解)
- Gym Class(优先队列+拓扑排序)
- poj3687 Labeling Balls 拓扑排序
- poj3687 Labeling Balls【拓扑排序】
- hdu1285 拓扑排序+优先队列
- HDU1285(拓扑排序+优先队列)
- JVM内存模型以及垃圾收集策略解析
- 《micro2440开发》第十章:tiny6410和micro2440的Jlink与RVDS/ADS调试对比学习
- 盈利相关
- 把log4j日志信息输出到数据库
- IE上网要密码 如何用好IE内容审查
- POJ3687 球的标签(拓扑排序+优先队列)
- java排序算法_010选择排序
- 极详细的ECC讲解 -OOB与ECC
- UVa 11292 - The Dragon of Loowater
- 深入浅出外观模式(一)
- alfresco V4.1.1.3 企业版启动错误日志分析
- [Android] ListView中getView的原理+如何在ListView中放置多个item
- JAVA编程思想读书笔记5:初始化与清理
- 我读Boosting Saliency CVPR 2012