UESTC 1150 排名表(拓扑排序、很容易错)
2016-07-17 15:37
477 查看
题目链接:
UESTC 1150 排名表
题意:
给出一个n个人的已知的m个排名顺序:a[i]在b[i]之前。输出这n个人的排名顺序的名次,如果有多解让编号为1的人的名次尽量小,然后让编号为2的人的名次尽量小,然后让编号为3的人的名次尽量小……。如果无解输出−1。
数据范围:0≤n≤200,0≤m≤40000。
分析:
要多读题
要多读题
要多读题
这题和POJ 3687 Labeling Balls一样的
一开始我以为直接用优先队列并且小元素先出队列:
priority_queue<int,vector<int>,greater<int> >que;
建立有向边:a[i]→b[i],依次把入度为0的点进队列,和普通的拓扑排序一样,并且这样做四个样例都过了。
然而一提交Wrong Answer On Test2。。。。。。。
这就非常的尴尬了。。。。。
想了好久才明白题目中让编号为1的人的名次尽量小,然后让编号为2的人的名次尽量小,然后让编号为3的人的名次尽量小……的含义。
换句话说:
对于编号为1:除了强制有优先关系的,在他前面不应该有其他的点
对于编号为2:在满足编号1的条件下和本身存在优先关系的,在他前面不应该有其他的点
…..
举个例子:
n=4,m=2
31
24
符合题意的编号顺序应该是:3,1,2,4
编号1−4的名次顺序是:2,3,1,4
这样保证了让编号为1的人的名次尽量小
如果如开头所说的用小元素先出的优先队列搞的话,那么得到的编号顺序是:2,3,1,4
每个编号对应的名次是:3,1,2,4,这样子就不是编号为1的名次尽量小了!
我们来考虑这个排序在多解时的最终状态的性质:编号大的靠后
那么我们可以反向建图,先将编号大的排列出来,然后将可能解锁的大编号也加进优先队列【并且优先队列是大元素先出】,依次排列就好了。
还要注意最后是输出每个人的对应名次,而不是输出排列顺序,实际上就是输出在排列顺序中的位置。
UESTC 1150 排名表
题意:
给出一个n个人的已知的m个排名顺序:a[i]在b[i]之前。输出这n个人的排名顺序的名次,如果有多解让编号为1的人的名次尽量小,然后让编号为2的人的名次尽量小,然后让编号为3的人的名次尽量小……。如果无解输出−1。
数据范围:0≤n≤200,0≤m≤40000。
分析:
要多读题
要多读题
要多读题
这题和POJ 3687 Labeling Balls一样的
一开始我以为直接用优先队列并且小元素先出队列:
priority_queue<int,vector<int>,greater<int> >que;
建立有向边:a[i]→b[i],依次把入度为0的点进队列,和普通的拓扑排序一样,并且这样做四个样例都过了。
然而一提交Wrong Answer On Test2。。。。。。。
这就非常的尴尬了。。。。。
想了好久才明白题目中让编号为1的人的名次尽量小,然后让编号为2的人的名次尽量小,然后让编号为3的人的名次尽量小……的含义。
换句话说:
对于编号为1:除了强制有优先关系的,在他前面不应该有其他的点
对于编号为2:在满足编号1的条件下和本身存在优先关系的,在他前面不应该有其他的点
…..
举个例子:
n=4,m=2
31
24
符合题意的编号顺序应该是:3,1,2,4
编号1−4的名次顺序是:2,3,1,4
这样保证了让编号为1的人的名次尽量小
如果如开头所说的用小元素先出的优先队列搞的话,那么得到的编号顺序是:2,3,1,4
每个编号对应的名次是:3,1,2,4,这样子就不是编号为1的名次尽量小了!
我们来考虑这个排序在多解时的最终状态的性质:编号大的靠后
那么我们可以反向建图,先将编号大的排列出来,然后将可能解锁的大编号也加进优先队列【并且优先队列是大元素先出】,依次排列就好了。
还要注意最后是输出每个人的对应名次,而不是输出排列顺序,实际上就是输出在排列顺序中的位置。
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <climits> #include <cmath> #include <ctime> #include <cassert> #include <vector> #include <queue> #define IOS ios_base::sync_with_stdio(0); cin.tie(0); using namespace std; typedef long long ll; const int MAX_N = 250; vector<int> vec[MAX_N]; int degree[MAX_N], ans[MAX_N]; priority_queue <int> que; void TopoSort(int n, int m) { while(!que.empty()) que.pop(); for(int i = 1; i <= n; ++i) { if(degree[i] == 0) que.push(i); } int total = n; while(!que.empty()) { int cur = que.top(); //cur是当前编号 ans[cur] = total--; //先排好的是靠后的元素 //printf("cur = %d ans[cur] = %d\n", cur, ans[cur]); que.pop(); for(int i = 0; i < vec[cur].size(); ++i) { int to = vec[cur][i]; degree[to]--; if(degree[to] == 0) que.push(to); } } if(total > 0) printf("-1\n"); //有环 else { for(int i = 1; i <= n; ++i) { if(i > 1) printf(" "); printf("%d", ans[i]); } printf("\n"); } } int main() { int T, n, m; scanf("%d", &T); while(T-- > 0) { scanf("%d%d", &n, &m); memset(degree, 0, sizeof(degree)); for(int i = 1; i <= n; ++i) { vec[i].clear(); } for(int i = 0; i < m; ++i) { //反向建图 int u, v; scanf("%d%d", &u, &v); degree[u]++; //!!!! vec[v].push_back(u); } TopoSort(n, m); } return 0; }
相关文章推荐
- 详解图的应用(最小生成树、拓扑排序、关键路径、最短路径)
- 优先队列(priority_queue)的C语言实现代码
- PHP 数据结构队列(SplQueue)和优先队列(SplPriorityQueue)简单使用实例
- 堆排序/优先级队列
- 初学图论-Kahn拓扑排序算法(Kahn's Topological Sort Algorithm)
- 反向拓扑排序 HDU 4857 逃生
- 优先队列<堆>
- 二叉堆
- HDU 3342
- 2367:Genealogical tree
- vijosP1016北京2008的挂钟 BFS + 优先队列
- 优先队列的学习笔记
- 优先队列的学习笔记
- #POJ1521#Huffman编码
- #NOIP1999#旅行家的预算
- 【UESTC】2015 UESTC Training for Data Structures
- 16.7.16 C 1744. 奶牛晒衣服
- hdu 1285 确定比赛名次 (简单的拓扑排序)
- hdu 2049 产生冠军(拓扑排序)
- hdu 1596 find the safest road(spfa算法)