hdu1285 确定比赛名次(拓扑排序)
2016-05-31 20:17
363 查看
http://acm.hdu.edu.cn/showproblem.php?pid=1285
题意:中文题求名次。
思路:刚接触拓扑排序,献上教程。第一种算是邻接矩阵的应用吧,很巧妙的算法,统计每个点入度的次数,将入度为0的元素从小到大依次输出。已经访问过的做标记,避免不必要的判断。复杂度O(n^2)。
第二种是基于前向星和优先队列的优化版,原来前向星就是邻接表去掉指针的简化版,ym某神。前一种要先遍历一次所有点,再找该点的相关点又要遍历一次。而这里把所有入度为0的点放入优先队列,利用优先队列的性质自动对其排列,这样相当于少了一次类似排序的遍历。不过要找下一个点需要边信息,所以还要整体遍历一次边。复杂度变为O(n+m),直接从62ms减到了15ms。
题意:中文题求名次。
思路:刚接触拓扑排序,献上教程。第一种算是邻接矩阵的应用吧,很巧妙的算法,统计每个点入度的次数,将入度为0的元素从小到大依次输出。已经访问过的做标记,避免不必要的判断。复杂度O(n^2)。
#include <stdio.h> #include <algorithm> #include <stdlib.h> #include <string.h> #include <iostream> using namespace std; typedef long long LL; const int N = 1000; const int INF = 0x3f3f3f3f; int deg , n; bool G ; void toposort() { int k; for(int i = 1; i <= n; i++)//n个节点一次一次的出,保证顺序防止混乱 { for(int j = 1; j <= n; j++)//找到入度为0的点 { if(deg[j] == 0) { if(i == n) printf("%d\n", j); else printf("%d ", j); k = j; deg[j]--; break; } } for(int j = 1; j <= n; j++)//与该入度为0点相邻的点因为他的离去而入度减一 { if(G[k][j] == true) { G[k][j] = false; deg[j]--; } } } } int main() { // freopen("in.txt", "r", stdin); int m, u, v; while(~scanf("%d%d", &n, &m)) { memset(G, false, sizeof(G)); memset(deg, 0, sizeof(deg)); for(int i = 1; i <= m; i++) { scanf("%d%d", &u, &v); G[u][v] = true; deg[v]++; } toposort(); } return 0; }
第二种是基于前向星和优先队列的优化版,原来前向星就是邻接表去掉指针的简化版,ym某神。前一种要先遍历一次所有点,再找该点的相关点又要遍历一次。而这里把所有入度为0的点放入优先队列,利用优先队列的性质自动对其排列,这样相当于少了一次类似排序的遍历。不过要找下一个点需要边信息,所以还要整体遍历一次边。复杂度变为O(n+m),直接从62ms减到了15ms。
#include <stdio.h> #include <algorithm> #include <stdlib.h> #include <string.h> #include <iostream> #include <queue> using namespace std; typedef long long LL; const int N = 1000; const int INF = 0x3f3f3f3f; int deg , head , n; struct node { int v, next; }edge ; void toposort() { priority_queue<int, vector<int>, greater<int> > que; int k; for(int i = 1; i <= n; i++) { if(deg[i] == 0) { que.push(i); deg[i]--; } } int num = 1; while(!que.empty()) { int u = que.top(); que.pop(); if(num == n) printf("%d\n", u); else printf("%d ", u); num++;//出队元素的个数 for(int i = head[u]; i != -1; i = edge[i].next) { deg[edge[i].v]--; if(deg[edge[i].v] == 0) que.push(edge[i].v); } } } int main() { // freopen("in.txt", "r", stdin); int m, u, v; while(~scanf("%d%d", &n, &m)) { memset(head, -1, sizeof(head)); memset(deg, 0, sizeof(deg)); int cnt = 0; for(int i = 1; i <= m; i++) { scanf("%d%d", &u, &v); int j; for(j = head[u]; j != -1; j = edge[j].next) { if(edge[j].v == v) break; } if(j == -1) { deg[v]++; edge[cnt].v = v; edge[cnt].next = head[u]; head[u] = cnt++; } } toposort(); } return 0; }
相关文章推荐
- 【HDU 5366】The mook jong 详解
- 【HDU 2136】Largest prime factor 详细图解
- 【HDU 1568】Fibonacci 数学公式 详解
- HDU 1568
- HDU1290
- HDU1568(Fobonacci公式)
- HDU ACM Step 2.2.2 Joseph(约瑟夫环问题)
- HDU 1405
- HDU 1297
- hdu 1205
- hdu 2087
- hdu 1016
- HDU 4898 The Revenge of the Princess’ Knight ( 2014 Multi-University Training Contest 4 )
- HDU 5592 ZYB's Premutation 线段树(查找动态区间第K大)
- HDU 5240 Exam (好水的题)
- HDU5237 Base64 大模拟
- HDU 1000
- HDU 1001
- HDU 1016 Prime Ring Problem
- HDU 1017 A Mathematical Curiosity