1089.拓扑排序
Time Limit: 1000 MS Memory Limit: 32768 KB
Description
给定一个有向图,若图无环,则将其进行拓扑排序并输出,否则输出IMPOSABLE。
第一行为两个整数n(1<=n<=1000)、m(1<=m<=100000);
之后m行,每行两个整数a、b表示一条从a到b的有向边。
若存在环,输出IMPOSABLE,否则输出一行用一个空格隔开的拓扑排序的结果,若存在多个结果,输出字典序最小的。
5 4
1 2
2 3
3 4
4 5
Sample Output
1 2 3 4 5
题目就已经很清楚的把题意给说出来了= =这就是一道拓扑排序的题目,如果有环输出imposable,否则输出字典序最小的拓扑排序。所以直接记录下来入度,从前往后遍历就可以了,模板题。
下面AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int t;
int ma[1005][1005];
int indegree[1005];
int toposort(int a)
{
int i,j,k;
for(i=1;i<=a;i++)
{
for(j=1;j<=a;j++)
{
if(indegree[j]==0)
{
indegree[j]--;
if(t==0)
{
cout<<j;
t++;
}
else
{
cout<<" "<<j;
}
for(k=1;k<=a;k++)
{
if(ma[j][k]==1)
{
indegree[k]--;
}
}
break;
}
}
}
return 0;
}
int goal(int a)
{
int i,j,k;
int flag;
int in[1005];
for(i=1;i<=a;i++)
{
in[i]=indegree[i];
}
for(i=1;i<=a;i++)
{
flag=0;
for(j=1;j<=a;j++)
{
if(in[j]==0)
{
flag=1;
in[j]=-1;
for(k=1;k<=a;k++)
{
if(ma[j][k])
in[k]--;
}
break;
}
}
if(flag==0)
return 0;
}
if(flag==1)
return 1;
return 0;
}
int main()
{
int i;
int x,y;
int n,m;
int k;
while(scanf("%d%d",&n,&m)!=EOF)
{
k=0;
t=0;
memset(ma,0,sizeof(ma));
memset(indegree,0,sizeof(indegree));
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
if(!ma[x][y])
{
ma[x][y]=1;
indegree[y]++;
}
}
if(!goal(n))
{
cout<<"IMPOSABLE"<<endl;
//cout<<"--------------------"<<endl;
continue;
}
toposort(n);
cout<<endl;
//cout<<"----------------------"<<endl;
}
return 0;
}