![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/* Name: 拓扑排序,判断有向图是否存在回路及自环,并统计每个顶点的前驱点数 Copyright: Author: Try86 Date: 15/04/12 22:25 Description: */ #include <queue> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> using namespace std; const int N = 10005; int sum, flag; int counts[N]; struct node { int v; node *next; node(int vv, node *p) { v = vv; next = p; } }; struct graph { int inDeg; //统计入度数 node *link; }G[N]; void init(int n) { for (int i=1; i<=n; ++i) { G[i].inDeg = 0; G[i].link = NULL; counts[i] = 0; } return ; } void buildG(int u, int v) { node *p = new node(v, G[u].link); G[u].link = p; ++G[v].inDeg; return ; } void topoSort(int n) { sum = 0; flag = true; queue<int> Q; for (int i=1; i<=n; ++i) {//入度数为0的点入队列 if (G[i].inDeg == 0) Q.push(i), --G[i].inDeg; } while (!Q.empty()) { int u = Q.front(); sum += counts[u]; //统计所有点的总的前驱点数 Q.pop(); for (node *p=G[u].link; p; p=p->next) { --G[p->v].inDeg; //与u邻接的点的入度数减1 if (G[p->v].inDeg == 0) { Q.push(p->v); counts[p->v] = counts[u] + 1;//统计点v的前驱点数 } } } for (int i=1; i<=n; ++i) {//判断是否有回路或自环 if (G[i].inDeg > 0) { flag = false; break; } } return ; } void del(node *p) { if (!p) return ; del(p->next); delete p; return ; } int main() { int n, m; while (scanf("%d%d", &n, &m) != EOF) { init(n); int u, v; for (int i=0; i<m; ++i) { scanf ("%d%d", &u, &v); buildG(v, u); //注意建图的顶点顺序 } topoSort(n); if (flag) printf ("%d\n", 888*n+sum); else printf ("-1\n"); for (int i=1; i<=n; ++i) del(G[i].link); } return 0; }