Input输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。
Output给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。
其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
Sample Input
4 3 1 2 2 3 4 3Sample Output
1 2 4 3
拓扑排序入门题。。。
题目输入给出多个队伍之间的排名前后关系,要求输出符合所给关系的排名。
前置知识:有向无环图必定存在拓扑序,可以进行拓扑排序找出其中满足条件的序列。
思考:何谓拓扑排序?我个人理解是按“度”排序。比如说,1队赢2队(有方向),那么我就将2队的度+1(可以理解为输的队伍的度+1)。;在排序的时候,度小的排在前面,每次找度为0的队伍,(度为0意味着该队伍在当前状态的图中没有队伍赢过他),然后该队伍就是当前状态图中最优的几个队伍中的一个队伍(可能同时有好几个度为0的队伍),也就是排名比其他队伍前!!!找到后就需要更新留下来的队伍的度(度为0的队伍都出去领奖了),输给出去领奖的队伍的队伍的度相应的减1(可以用邻接矩阵实现,也可以用vector,还有很多骚操作,条条大路通罗马)。至于为什么减1。。。因为输一次度就加一,赢你的队伍已经从图上暂时剔除了,所以度减1咯。。。
然后就是。。。重复上面的找度为零的操作。。。。。。。。。。。。。。。。。。。。。。。。。直到找到拓扑序。。。。。
有一个问题就是:如果在某个找度为零的过程找不到度为零的队伍呢? ans: 这就说明存在环!!!!!!存在环就没办法确定排名了,但是这道题已经说明一定存在解,所以不会出现环的情况。
附AC代码:
//#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstdio>
using namespace std;
#define up(i,j,k) for(int i=j;i<k;i++)
#define uup(i,j,k) for(int i=j;i>=k;i--)
#define mem(i,j) memset(i,j,sizeof i)
#define sfi(i) scanf("%d",&i)
#define sfl(i) scanf("%lld",&i)
#define sfd(i) scanf("%lf",&i)
#define sfc(i) scanf("%c",&i)
#define sfs(i) scanf("%s",i)
#define sf() cout<<"This is a flag!"<<endl;
#define wt(i) cout<<"This is "<<i<<endl;
#define ll long long
#define mod(x) (x)%mod
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int MAX=5e2+50;
struct node
{
int du;
int t;
int nxt[MAX]; //数据量比较小,所以可以随便构建结构体。。。只要保证实现能访问他的下一个就好。
}p[MAX];
bool mapp[MAX][MAX]; //判重,,其实不需要。。。重边在这里不影响。。。
bool vis[MAX];
int num[MAX];
int main()
{
int n,m;
//freopen("d:\\1.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
int a,b;
mem(p,0);
mem(mapp,0);
up(i,0,m)
{
sfi(a);
sfi(b);
if(!mapp[a][b])
mapp[a][b]=1;
else
continue;
p[b].du++;
p[a].nxt[p[a].t++]=b;
}
mem(vis,0);
up(i,1,n+1) //n个人。。
{
int xx=-1;
up(j,1,n+1)
{
if(!vis[j]&&p[j].du==0) //找到度为0的点
{
xx=j;
break;
}
}
if(xx==-1) //存在环。。。
{
break;
}
vis[xx]=1;
num[i]=xx;
for(int j=0;j<p[xx].t;j++) //更新与他相连的点的度
{
p[p[xx].nxt[j]].du--;
}
}
up(i,1,n)
{
printf("%d ",num[i]);
}
printf("%d\n",num[n]);
}
return 0;
}