HDU 1285 - 确定比赛名次 ( 拓扑排序 )
题意
给出N个队伍标号为1-N
现给出一些队伍的胜负关系,比如 p1, p2表示 p1战胜了p2
求一个排名,要求输出时编号小的队伍在前。
数据保证不会有环
思路
拓扑排序:每次找入度==0的点, 将这个点和从它发射的边删掉。在常规的拓扑排序中,若找不到这样的点说明有环(故拓扑排序可以判断图中是否成环)。但这道题已经确保不会出现这样的情况。
AC代码(直接求)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 500+10;
int d[maxn][maxn], in[maxn], t[maxn];
int n, m;
void topo()
{
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(d[i][j])
in[j]++;
for(int i = 1; i <= n; i++){
int cnt = 1;
while( in[cnt] != 0 )
cnt++;
t[i] = cnt;
in[cnt] = -1;
for(int j = 1; j <= n; j++)
if(d[cnt][j])
in[j]--;
}
}
int main()
{
int fr, to;
while( ~scanf("%d%d",&n, &m) ){
memset(in, 0, sizeof in);
memset(t, 0, sizeof t);
memset(d, 0, sizeof d);
while( m-- ){
scanf("%d%d",&fr,&to);
d[fr][to] = 1;
}
topo();
for(int i = 1; i <= n; i++){
if(i != 1)
printf(" ");
printf("%d",t[i]);
}
printf("\n");
}
return 0;
}
AC代码(利用优先队列)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 500+10;
int d[maxn][maxn], in[maxn];
int n, m;
priority_queue<int, vector<int>, greater<int> > que;
void topo()
{
for(int i = 1; i <= n; i++)
if(in[i]==0)
que.push(i);
int i = 0;
while(!que.empty()){
int t = que.top();
que.pop();
if(i!=0) printf(" ");
else i++;
printf("%d", t);
for(int j = 1; j <= n; j++){
if(!d[t][j]) continue;
in[j]--;
if(in[j]==0)
que.push(j);
}
}
printf("\n");
}
int main()
{
int fr, to;
while( ~scanf("%d%d",&n, &m) ){
memset(in, 0, sizeof in);
memset(d, 0, sizeof d);
while( m-- ){
scanf("%d%d",&fr,&to);
if(d[fr][to])
continue;
d[fr][to] = 1;
in[to]++;
}
topo();
}
return 0;
}