反向建图!!反向遍历!!
#include<stdio.h>
#include<iostream>#include<string.h>
using namespace std;
int rudu[205];
int mp[205][205];
int vis[205];
int ans[205];
int n,m;
int main()
{
int t;
int x,y,flag;
cin>>t;
while(t--)
{
memset(rudu,0,sizeof(rudu));
memset(mp,0,sizeof(mp));
memset(vis,0,sizeof(vis));
memset(ans,0,sizeof(ans));
cin>>n>>m;
flag=0;
for(int i=0;i<m;i++)
{
cin>>x>>y;
if(mp[y][x]==0)
rudu[x]++;
mp[y][x]=1;
if(x==y)
flag=1;
}
if(flag==1)
{
cout<<"-1"<<endl;
continue;
}
int cnt=n;
while(1)
{
int k=-1;
for(int i=n;i>=1;i--)
{
if(rudu[i]==0&&vis[i]==0)
{
k=i;
vis[i]=1;
break;
}
}
if(k==-1) break;
ans[k]=cnt--;
for(int j=1;j<=n;j++)
{
if(mp[k][j]==1) rudu[j]--;
}
}
if(cnt!=n)
{
cout<<"-1"<<endl;
continue;
}
for(int i=1;i<=n;i++)
{
if(i!=1) cout<<" ";
cout<<n-ans[i];
}
cout<<endl;
//}
}
return 0;
}
快速的:http://www.cnblogs.com/Tree-dream/p/5748312.html
利用优先队列来做
#include <stdio.h>
#include <string.h>
#include <queue>
#define maxn 210
using namespace std;
int digree [ maxn ]; //这个就是入度值。
int judge [ maxn ][ maxn ]; //这个是用来判断有没有重边的。
int location [ maxn ];
int m,n;
priority_queue<int >s; //这个是默认的最大优先队列。
int topsort()
{
int num = n;
for( int i = 1 ; i <= n ; i++ )
if(!digree[ i ]) s.push( i );
if( s.empty() ) return 0; //如果没有入度为0的,则说明构成了一个环。
while( !s.empty() )
{
int tmp =s.top();
s.pop();
location [ tmp ] = num--;
for( int i = 1 ; i <= n ; i++ )
{
if( judge[ i ][ tmp ] )
{
judge[ i ][ tmp ] = 0;
digree[ i ] --;
if( !digree[ i ] ) s.push( i );
}
}
}
if( num != 0 ) return 0; //如果这里Num 不能等于0,那么说明最少还有两个是无法确定的。
return 1;
}
int main()
{
int t,a,b;
scanf("%d",&t);
while( t -- )
{
memset( digree , 0 , sizeof( digree ) );
memset( judge , 0 , sizeof( judge ) );
memset( location , 0 , sizeof( location ) );
scanf("%d%d",&n,&m);
for( int i = 1 ; i <= m ; i ++ )
{
scanf("%d%d",&a,&b);
if(judge[ a ][ b ] > 0) continue; //判重。
judge[ a ][ b ] = 1;
digree [ a ] ++;
}
a = topsort();
if( a ) {
int i = 1;
for( ; i < n ; printf("%d ",location[ i++ ]) );
printf("%d\n",location[ i ]);
}
else printf("-1\n");
}
return 0;
}