交换节点 - 环

树上交换节点
给定一棵树,每个节点有一个权值。现在每次可以交换任意两个节点的权值,请问最少多少次交换可以使得每个节点的权值等于它的编号?
保证给出的权值是一个排列,也就是说保证一定有解。
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 256M,其他语言512M
输入描述:
第一行输入一个正整数
n
,代表树上的节点数量。
第二行输入
n
个正整数
a_i
,第
i
个正整数
a_i
i
号节点的权值,
a_i
互不相同。
接下来的
n-1
行,每行输入两个正整数
u
v
,代表
u
号节点和
v
号节点有一条边相连。



输出描述:
一个整数,代表最小的交换次数。
示例1
输入例子:
4
2 1 4 3
1 2
2 3
2 4
输出例子:
2
例子说明:
第一次交换1号节点和2号节点的权值,四个点的权值变成[1,2,4,3]
第二次交换3号节点和4号节点的权值,四个点的权值变成[1,2,3,4]
 
public class Program {
    public static void Main() {
        int n = int.Parse(System.Console.ReadLine());
        int[] a = new int[n + 1]; //输入下标对应数据
        string[] readArry = System.Console.ReadLine().Split();
        for (int i = 0; i < readArry.Length; i++) {
            a[i + 1] = int.Parse(readArry[i]);
        }
        for (int i = 0; i < n - 1; i++) {
            System.Console.ReadLine();//无需关系树结构 输入
        }

        int ringNum = 0;//环数
        bool[] ergodic = new bool[n + 1];

        for (int i = 1; i < n + 1; i++) {
            if (!ergodic[i]) {
                ringNum++;
                int j = i;//环遍历下标
                while (!ergodic[j]) {
                    ergodic[j] = true;
                    if (j != a[j]) {
                        j = a[j];
                    }
                }


            }

        }
        
        System.Console.WriteLine(n-ringNum);        
    }
}

 

posted @ 2025-03-18 15:32  燕钰达  阅读(27)  评论(0)    收藏  举报