题目:
http://acm.hdu.edu.cn/showproblem.php?pid=2647
拓扑排序方法如下:
(1)从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它.
(2)从网中删去该顶点,并且删去从该顶点发出的全部有向边.
(3)重复上述两步,直到剩余的网中不再存在没有前趋的顶点为止.
第一次做拓扑排序,有几点要说明一下:
1.vector是一个容器,可以动态分配内存,存储方式是线性的,他有几个常用的函数:
s[b].push_back(a):把a放到b这一数组后面;
s[b].size():测量在s[b]后面放了几个元素。
2.pair中的make_pair(x,y)可以把两个数据组合成一个,在函数需要返回两个整数的时候也可以用这个函数。
3.注意输出的结果要用长整形。
源代码:
1 #include <iostream>
2 #include<queue>
3 #include<vector>
4 #include<stdio.h>
5 #include<stdlib.h>
6 #include<cstring>
7 #define maxn 10005
8 using namespace std;
9 struct {int id;} point[maxn];//节点在排序中所处位次
11 typedef pair<int,int>Pair;
12 vector<int>map[maxn]; //记录拓扑排序的方式
13 queue<Pair>q;
14 int m,n;
15 __int64 ans;
16 int from[maxn];
17 bool topo(){
18 int count=0;
19 for(int i=1;i<=n;i++){
20 if(from[i]==0){
21 q.push(make_pair(i,0));
22 count++;
23 }
24 }
25 while(!q.empty()){
26 int x=q.front().first;
27 int y=q.front().second;
28 q.pop();
29 for(int i=0;i<map[x].size();i++){
30 int z=map[x][i];
31 point[z].id=max(point[z].id,y+1);
32 from[z]--;
33 if(from[z]==0){
34 q.push(make_pair(z,point[z].id));
35 count++;
36 }
37 }
38 }
39 ans=0;
40 for(int i=1;i<=n;i++)
41 ans+=point[i].id;
42 if(count==n)return true; //不存在环
43 else return false;
44 }
45
46 int main()
47 {
48 int a,b;
49 while(scanf("%d %d",&n,&m)!=EOF){
50 memset(from,0,sizeof(from)); //入度
51 for(int i=1;i<=n;i++){
52 point[i].id=0;
53 map[i].clear(); //注意清除上一次的记录
54 }
55 for(int i=1;i<=m;i++){
56 scanf("%d %d",&a,&b);
57 map[b].push_back(a); //注意不要放反了
58 from[a]++;
59 }
60 if(topo())
61 printf("%I64d\n",ans+=888*n);
62 else
63 printf("-1\n");
64
65
66 }
67 return 0;
68 }