SDNU 1089.拓扑排序(拓扑判环小顶堆)
Description
给定一个有向图,若图无环,则将其进行拓扑排序并输出,否则输出IMPOSABLE。
Input
第一行为两个整数n(1<=n<=1000)、m(1<=m<=100000);
之后m行,每行两个整数a、b(0 < a, b <= n)表示一条从a到b的有向边。
之后m行,每行两个整数a、b(0 < a, b <= n)表示一条从a到b的有向边。
Output
若存在环,输出IMPOSABLE,否则输出一行用一个空格隔开的拓扑排序的结果,若存在多个结果,输出字典序最小的。
Sample Input
5 4 1 2 2 3 3 4 4 5
Sample Output
1 2 3 4 5
Source
Unknown
#include<bits/stdc++.h> using namespace std; int n, m, a, b, d[1000+8], num, cnt; vector<int>t[1000+8]; queue<int>q; int ans[1000+8], sign[1000+8]; bool flag = 0; priority_queue<int, vector<int>, greater<int> >you; void bfs() { while(!you.empty()) { int f = you.top(); you.pop(); if(flag)printf(" "); flag = 1; printf("%d", f); for(int i = 0; i<t[f].size(); i++) { d[t[f][i]]--; if(d[t[f][i]] == 0 && !sign[t[f][i]]) { you.push(t[f][i]); sign[t[f][i]] = 1; } // } } } } int get(int miao)//判环 { int in[1000+8],si[1000+8]; for(int i = 0; i <= miao; i++) { in[i] = d[i]; si[i] = sign[i]; } num = miao; while(!q.empty()) { int f = q.front(); num--; q.pop(); for(int i = 0; i<t[f].size(); i++) { in[t[f][i]]--; if(!in[t[f][i]] && !si[t[f][i]]) { q.push(t[f][i]); si[t[f][i]] = 1; } } } return num; } int main() { while(~scanf("%d%d", &n, &m) && (n+m)) { memset(d, 0, sizeof(d)); memset(sign, 0, sizeof(sign)); for(int i = 0; i<1000+8; i++)t[i].clear(); while(!q.empty())q.pop(); for(int i = 0; i<m; i++) { scanf("%d%d", &a, &b); t[a].push_back(b);//存图 d[b]++;//入度++ } for(int i = 1; i <= n; i++) { if(!d[i] && !sign[i])//查找入度为0的节点,再插入队列,并标记它用过了 { q.push(i); you.push(i); sign[i] = 1; } } if(get(n) == 0)//如果不存在环 { bfs();//用bfs输出结果 } else printf("IMPOSABLE\n"); } return 0; }