您的位置:首页 > 其它

#sicily#1001.Ordering Tasks

2016-12-06 13:41 323 查看
source:http://soj.sysu.edu.cn/show_problem.php?pid=1001&cid=2388 密码:gjr

闲话

本题难搞之处在于数据量太大,到了100000的级别。如果开二维数组来存会爆内存。可以用vector数组来存储。

拓扑排序算法用kahn算法

算法原理简述

下面是来自维基的伪代码

L ← Empty list that will contain the sorted elements
S ← Set of all nodes with no incoming edges
while S is non-empty do
remove a node n from S
add n to tail of L
for each node m with an edge e from n to m do
remove edge e from the graph
if m has no other incoming edges then
insert m into S
if graph has edges then
return error (graph has at least one cycle)
else
return L (a topologically sorted order)


大概意思是,每次都从0 indegree(入度)队列中选择indegree为0的节点,放到已排好序列中。然后删除以节点为起点的边。如果有节点因此indegree为0, 放入0 indegree队列中。

源代码

对于本题,由于要求最小字典序输出,0 indegree队列采用优先队列。

#include <cstdio>
#include <queue>
#include <cstring>
#include <vector>

using namespace std;

int inDegree[100010];
struct cmp {
bool operator()(const int &i, const int &j) {
return (i > j);
}
};
vector<int> isLinked[100010];
priority_queue<int, vector<int>, cmp> queueToSort;
int n, length;
int resultList[100010];

int main() {
int t, m, a, b;
scanf("%d", &t);
while(t--) {
// initialize
scanf("%d", &n);
memset(inDegree, 0, (100010)*sizeof(int));
for(int i = 1; i < n+1; i++) {
isLinked[i].clear();
}

scanf("%d", &m);
// read in
while(m--) {
scanf("%d%d", &a, &b);
isLinked[a].push_back(b);
inDegree[b]++;
}

for (int i = 1; i <= n; i++) {
if (0 == inDegree[i]) { queueToSort.push(i); };
}
int firstNode;
length = 0;
while(!queueToSort.empty()){
firstNode = queueToSort.top();
queueToSort.pop();
// output
resultList[length] = firstNode;
length++;
// delete edges
for (int i = 0; i < isLinked[firstNode].size(); i++) {
inDegree[isLinked[firstNode][i]]--;
if (0 == inDegree[isLinked[firstNode][i]]) {
queueToSort.push(isLinked[firstNode][i]);
}
}
}
for(int i = 0; i < length; i++) {
printf("%d ", resultList[i]);
}
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: