图相关算法

拓扑排序及其变种

比赛排名

题目描述: 有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。

输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。

4 3
1 2
2 3
4 3

给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。

1 2 4 3

其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。

//错误方法 
import java.util.*;

class Node{
    int val; //0,1,2
    int out; //出度
    List<Node> prev; //上一个节点
    
    public Node(int val, int in){
        this.val = val;
        this.out = out;
        this.prev = new ArrayList<>();
    }
}

public class Main {
    public static void main(String[] args) {
        //Scanner in = new Scanner(System.in);
        //int a = in.nextInt();
        //System.out.println(a);
        Scanner in=new Scanner(System.in);
        int N=in.nextInt();
        int M=in.nextInt();
        
        Node[] nodes = new Node[N];
        for(int i=0; i<N; i++) {
            nodes[i] = new Node(i+1, 0);
        }
        
        Deque<Node> zeros = new LinkedList<>();
        for(int i=0; i<M; i++){
            int f = in.nextInt();
            int t = in.nextInt();
            nodes[f-1].out++;
            nodes[t-1].prev.add(nodes[f-1]);
        }
        for(int i=0; i<N; i++){
            if(nodes[i].out == 0){
                zeros.offerLast(nodes[i]);
            }
        }
        
        Stack<Integer> res = new Stack<>();
        while(!zeros.isEmpty()){
            List<Integer> one = new ArrayList<>();
            int size = zeros.size();
            for(int i=0; i<size; i++){
                Node tmp = zeros.pollFirst();
                //System.out.println(tmp.val);
                one.add(tmp.val);
                for(Node node : tmp.prev){
                    if(--node.out == 0){
                        zeros.add(node);
                    }
                }
            }
            Collections.sort(one, (a,b) -> b.compareTo(a));
            for(Integer i : one) res.push(i);
        }
        while(!res.isEmpty()){
            if(res.size() == 1){
                System.out.print(res.pop());
            }
            else{
                System.out.print(res.pop()+" ");
            }
        }
    }
}
//正确方法:每次找入度为0的点都从最小索引开始遍历
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstring>
using namespace std;
int G[501][501];
int n,m;
int shu[501];
int main()
{
    int i,x,y,j,h;
    while(cin>>n>>m)
    {
        memset(G,0,sizeof(G));
        memset(shu,0,sizeof(shu));
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            if(x<=n&&y<=n)
            {
                if(G[x][y]==0)
                {
                    G[x][y]=1;
                    shu[y]++;
                }
            }
        }
        for(i=1;i<=n;i++)
        {
            h=1;
            for(j=1;j<=n;j++)
            {
                if(shu[j]==0)
                {
                    h=j;
                    break;
                }
            }
            if(i<n)
            {
                cout<<h<<' ';
            }
            else
            {
                cout<<h<<endl;
            }
            shu[h]=-1;
            for(j=1;j<=n;j++)
            {
                if(G[h][j]==1)
                {
                    G[h][j]=0;
                    shu[j]--;
                }
            }
        }
    }
    return 0;
}
posted @ 2021-08-18 10:07  bacmive  阅读(58)  评论(0编辑  收藏  举报