Java实现Labeling Balls(拓扑排序的应用)

1 问题描述
给出一些球,从1N编号,他们的重量都不相同,也用1N标记加以区分(这里真心恶毒啊,估计很多WA都是因为这里),然后给出一些约束条件,< a , b >要求编号为 a 的球必须比 b 轻,现在要求按编号升序输出每个球的重量,如果有多种解,输出字典序最小的那个。

例如:

input:

1

5 4
5 1
4 2
1 3
2 3

output:

2 4 5 3 1

package com.liuzhen.practice;

import java.util.ArrayList;
import java.util.Scanner;

public class Main {
    public static int count;   //顶点的编号
    public static int[] degree;   //计算顶点的入度
    public static ArrayList<edge>[] map;  //表示图
    public static ArrayList<String> result1 = new ArrayList<String>();
    
    static class edge {
        public int a;    //边的起点
        public int b;    //边的终点
        
        public edge(int a, int b) {
            this.a = a;
            this.b = b;
        }
    }
    
    @SuppressWarnings("unchecked")
    public void init(int n) {
        count = n;
        degree = new int[n + 1];
        map = new ArrayList[n + 1];
        for(int i = 0;i <= n;i++) {
            map[i] = new ArrayList<edge>();
            degree[i] = 0;
        }
        return;
    }
    
    public String getResult() {
        String result = "";
        int[] ans = new int[degree.length];
        while(count >= 1) {
            int i = degree.length - 1;
            for(;i >= 1;i--) {
                if(degree[i] == 0) {
                    ans[i] = count--;
                    degree[i]--;
                    for(int j = 0;j < map[i].size();j++)
                        degree[map[i].get(j).b]--;
                    break;
                }
            }
            if(i == 0)   //此时给定图存在回环
                return "-1";
        }
        StringBuilder temp = new StringBuilder("");
        for(int i = 1;i < ans.length;i++) {
            temp.append(ans[i]);
            if(i != ans.length - 1)
                temp.append(" ");
        }
        result = temp.toString();
        return result;
    }
    
    public static void main(String[] args) {
        Main test = new Main();
        Scanner in = new Scanner(System.in);
        int t = in.nextInt();     //要输入图的个数
        while(t > 0) {
            t--;
            int n = in.nextInt();
            test.init(n);
            int k = in.nextInt();   //输入图的边的个数
            for(int i = 0;i < k;i++) {
                int a = in.nextInt();
                int b = in.nextInt();
                boolean judge = true;
                for(int j = 0;j < map[b].size();j++) {   //检查重复边
                    if(map[b].get(j).b == a){
                        judge = false;
                        break;
                    }
                }
                if(judge && a != b) {
                    map[b].add(new edge(b, a));
                    degree[a]++;  //顶点a的入度自增1
                }
            }
            result1.add(test.getResult());
        }
        for(int i = 0;i < result1.size();i++) {
            System.out.println(result1.get(i));
        }
    }
}

运行结果:

4
1
2
3
3
5
1
1
8
1
8
4 5 3 1
1 6 2 7 8 3 4 9 10
  • 18
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 20
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值