逆拓扑排序 HDU2647Reward
这个题如果用邻接矩阵的话,由于n比较大,会超内存,所以选用邻接表的形式。还有就是这个题有那个等级的问题,一级比一级的福利高,所以不能直接拓扑排序,而是反过来,计算出度,找出度为0的顶点,然后更新出度数组,等级更新的时候要判断是否比原来的等级大,具体看代码
1 /************************************************************************* 2 > File Name: hdu_1647.cpp 3 > Author: 4 > Mail: 5 > Created Time: 2015年03月28日 星期六 16时18分47秒 6 ************************************************************************/ 7 8 #include<iostream> 9 #include <cstdio> 10 #include <cstring> 11 #include <stdlib.h> 12 using namespace std; 13 const int N = 10004; 14 int OutDegree[N];//出度 15 struct Node{//邻接表 16 int start; 17 struct Node *next; 18 }; 19 Node *node[N]; 20 int n, m, ans; 21 int level[N];//等级 22 bool Topo() 23 { 24 int cnt = 0;//统计个数 25 for (int i = 1; i <= n; i++) 26 { 27 for (int j = 1; j <= n; j++) 28 { 29 if (OutDegree[j] == 0)//找到出度为0的顶点 30 { 31 cnt++; 32 OutDegree[j]--; 33 ans += level[j] + 888; 34 Node *tmp = node[j]->next; 35 while (tmp != NULL)//将所有跟他有关的边去掉 36 { 37 OutDegree[tmp->start]--; 38 level[tmp->start] = max(level[tmp->start], level[j] + 1);//比较等级之间的关系,取较大的那个 39 tmp = tmp->next; 40 } 41 } 42 } 43 } 44 if (cnt == n)//判断是否存在环 45 return true; 46 return false; 47 } 48 int main() 49 { 50 while (~scanf("%d %d", &n, &m)) 51 { 52 ans = 0; 53 int a, b; 54 memset(level, 0, sizeof(level)); 55 memset(OutDegree, 0, sizeof(OutDegree)); 56 for (int i = 1; i <= n; i++)//初始化 57 { 58 node[i] = (Node *)malloc(sizeof(Node)); 59 node[i]->start = 0; 60 node[i]->next = NULL; 61 } 62 63 for (int i = 0; i < m; i++) 64 { 65 scanf("%d %d", &a, &b); 66 OutDegree[a]++; 67 Node *tmp = node[b]; 68 while (tmp->next != NULL) 69 tmp = tmp->next; 70 Node *new_node = (Node *)malloc(sizeof(Node)); 71 new_node->start = a; 72 new_node->next = NULL; 73 tmp->next = new_node; 74 } 75 if (Topo()) 76 printf("%d\n", ans); 77 else 78 puts("-1"); 79 for (int i = 1; i <= n; i++) 80 free(node[i]); 81 } 82 83 return 0; 84 }