BZ 内心:
看了一晚上拓扑排序(也顺便看了下bfs和dfs),然后就找到了一道正宗的拓扑题(也看了师哥发的PPt)。特发此文,悼念一下今晚就die掉的拓扑。
Description
给定一个有向图,若图无环,则将其进行拓扑排序并输出,否则输出IMPOSABLE。
Input
第一行为两个整数n(1<=n<=1000)、m(1<=m<=100000);
之后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
思路:(这里我就直接复制一下PPT里的了)
好吧!万恶的选课系统。。。。
#include<stdio.h>
#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string.h>
#include<math.h>
using namespace std ;
typedef long long ll;
#define maxn 10000005
#define INF 0x3f3f3f3f//将近int类型最大数的一半,而且乘2不会爆int
int main()
{
// vector<vector<int >>g(1005);
vector<int >g[10005];
int ru[10005], s[10005];
int n, m;
scanf("%d %d", &n, &m);
for(int i=1; i<=n; ++i)
g[i].clear();//清空容器
memset(ru, 0, sizeof(ru));
for(int i=0; i<m; ++i)
{
int a, b;
scanf("%d %d", &a, &b);
g[a].push_back(b);//存有向图,将b存入a中
ru[b]++;//记录入读=度
}
int x=0/;
for(int i=0; i<n; ++i)//循环n遍。
{
for(int j=1; j<=n; ++j)
{
if(ru[j] == 0)
{
s[x]=j;
x++;
ru[j] = -1;//删除j点
for(int k=0; k<g[j].size(); ++k)//将g[j]链表里的所有的点的入度都减1
ru[g[j][k]]--;
break;
}
}
}//以下按输出格式输出
int sum=0;
for(int i=0; i<n; ++i)
sum+=s[i];
if(sum == (1+n)*n/2)
{
for(int i=0; i<n; ++i)
if(i != n-1)
printf("%d ", s[i]);
else
printf("%d\n", s[i]);
}
else
printf("IMPOSABLE\n");
return 0;
}
Ps:其实本题数据不大,可用二维数组存图,刚好可以飘过。。。。。
(我好像还CE、RE了一次,,,请各位小友注意!)