Time Limit: 1 second
Memory Limit: 128 MB
【问题描述】
你是一个体育报社的记者,你接受到一个艰难的任务:有N支足球队参加足球比赛,现在给你一些比赛的结果,需要你给出各支球
队的排名,从1到N。
以下是给你的一些信息:
(1) 没有平局;
(2) 不同的球队排名不能相同;
(3) 对于所有满足(1<=a),(a小于b),(b<=n),第a名的球队一定可以打败第b名的球队。
给你部分比赛结果,要求给出排名,并且判断是否存在另一种排名方法满足给你的比赛结果。
【数据范围】
30%的数据 (1<=N<=7,1<=M<=15)
60%的数据(1<=N<=100,1<=M<=2000)
【输入格式】
第一行输入N(1<=N<=5000),表示球队的数量,编号为1到N。第二行输入M(1<=M<=100,000),表示给出的比赛场数,接下来M行,每
行两个整数X_i,Y_i,表示X_i能打败Y_i。
【输出格式】
输出包含N+1行,前N行描述球队的排名,第i个数表示第i名的球队,第N+1行包含一个整数,如果为0表示不存在其他的排名方法,否则为1表示还有其他的排名方法。
Sample Input
4
5
1 2
3 1
3 2
3 4
4 1
Sample Output
3
4
1
2
0
Sample Input1
3
2
2 1
2 3
Sample Output1
2
1
3
1
【题目链接】:http://noi.qz5z.com/viewtask.asp?ID=t075
【题解】
拓扑排序;
对于给的关系(x,y)
建一条从x指向y的单向边;
y的入度递增;
然后做拓扑排序;
每次找入度为0的点;
(直接输出)
然后修改它的邻点的入度;(递减1)
如果有一次找到的入度为0的点大于1;
就说明有多个拓扑序;
说明有多个排名;
否则没有;
(平台没有特判,每次输出的时候找标号最小的输出,[斜眼笑])
【完整代码】
#include <cstdio>
#include <vector>
using namespace std;
#define rei(x) scanf("%d",&x)
#define rep1(i,x,y) for (int i = x;i <= y;i++)
const int MAXN = 5e3+100;
int n,m,du[MAXN],yes = 0;
vector <int> g[MAXN];
int main()
{
//freopen("F:\rush.txt","r",stdin);
rei(n);
rei(m);
rep1(i,1,m)
{
int x,y;
rei(x);rei(y);
du[y]++;
g[x].push_back(y);
}
while (true)
{
int cnt = 0,j=-1;
rep1(i,1,n)
if (du[i]==0)
{
cnt++;
if (cnt==1) j = i;
}
if (cnt>1) yes = 1;
if (j==-1)
break;
du[j] = -1;
int len = g[j].size();
rep1(i,0,len-1)
du[g[j][i]]--;
printf("%d
",j);
}
printf("%d
",yes);
return 0;
}