算法训练#19:有向图(数组形式存取边)的初涉猎以及简单计算

30 阅读2分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 22 天,点击查看活动详情

第一题

Mocha and Hiking

题目理解

题目给出一个具有n+1n+1个节点和2n12n-1条有向边的图,其中边的分布是这样的:

  1. 其中的n1n-1条边是连接第ii和第i+1i+1个节点的(1in1)(1\le i\le n-1)
  2. 其余的nn条边的情况以一个数组表示:数组中的第ii项若称为ai(1in)a_i(1\le i\le n),则若ai=0a_i=0,边的方向就是从第ii个节点向第n+1n+1个节点,若ai=1a_i=1,边的方向就是从第n+1n+1个节点向第ii个节点

要求我们找到一条仅经过每个节点一次的路径

输入

输入整数tt,代表案例个数,1t201\le t\le 20
每个案例第一行输入1个整数nn1n1041\le n\le 10^{4} 每个案例的第二行输入nn个整数,表示剩下的边的方向

输出

每个案例输出n+1n+1个整数——代表找出的路径

思路

对于一个图,我们尽量把它构建出来,才可以去寻找相关规律。在构建测试样例图的时候,我们可以知道,若an1=0a_{n-1}=0,也就是第nn个节点存在一条向第n+1n+1个节点的边,那么,据题目可以知道,此时图已形成一条路径(1->n+1),所以可以直接得出结果;若并非如此,则我们可以找一条这这样的路:从1->n的路径中的某一部分插入第n+1n+1个节点,为此,我们需要一个特定的取值:假设ai=0,ai+1=1a_{i}=0,a_{i+1}=1,就可以把路径从1->i->i+1->...->n变成1->i->n+1->i+1->...->n,也就是说,遍历a数组,找到一个1就可以了。

代码

import java.util.Scanner;

public class mocha_and_hiking {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        for (int i = 0; i < t; i++) {
            int n = sc.nextInt();
            int[] a = new int[n];
            for (int i1 = 0; i1 < n; i1++) {
                a[i1] = sc.nextInt();
            }
            //作为存取路径的数组
            int[] b = new int[n + 1];
            for (int i1 = 0; i1 < n + 1; i1++) {//给路径赋值为思路所说到的特殊情况
                b[i1] = i1 + 1;
            }
            if(a[n-1]!=0) {//进行判定,若括号内容为false,就可以直接输出答案
                int mark=0;
                //找到插入点
                for (int i1 = 0; i1 < n; i1++) {
                    if(a[i1]==1){
                        mark=i1;
                        break;
                    }
                }
                //把路径换成正确路径
                int change=b[n];
                for (int i1 = mark; i1 < n+1; i1++) {
                    int temp=b[i1];
                    b[i1]=change;
                    change=temp;
                }
            }
            for (int i1 = 0; i1 < n+1; i1++) {
                System.out.print(b[i1]+" ");
            }
            System.out.println();
        }
    }
}

第二题

Who's Opposite?

题目理解

有若干个人均匀地坐在一张圆桌上,已知aa的对面是bb,请求出cc的对面是谁

输入

输入整数tt,代表案例个数,1t100001\le t\le 10000
每个案例第一行输入3个整数a,b,ca,b,c1a,b,c1081\le a,b,c\le 10^{8}

输出

每个案例输出11个整数——cc的对面是谁,若前面的aba,b对面的关系不成立或者找不到cc的对面,则输出-1

思路

我们可以借由aa的对面是bb推导出整个桌上的人数的一半,从而求出整张桌子的人数,若前面的aba,b对面的关系不成立,那么求出来的人数肯定小于aabb其中一个的,除此之外就是要注意桌上到底有没有cc这个人了,若cc大于求出的全体人数,那他不可能在桌上,就自然找不到对面是谁了

代码

import java.util.Scanner;

public class who_is_opposite {
    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        for (int i = 0; i < t; i++) {
            int a=sc.nextInt();
            int b=sc.nextInt();
            int c=sc.nextInt();
            int ans=0;
            int half=Math.abs(a-b);
            int all=half*2;
            if(a>all||b>all||c>all)
                ans=-1;
            else{
                ans=half>=c?c+half:c-half;
            }
            System.out.println(ans);
        }
    }
}