pat1067. Sort with Swap(0,*) (25)

1067. Sort with Swap(0,*) (25)

时间限制
150 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Given any permutation of the numbers {0, 1, 2,..., N-1}, it is easy to sort them in increasing order. But what if Swap(0, *) is the ONLY operation that is allowed to use? For example, to sort {4, 0, 2, 1, 3} we may apply the swap operations in the following way:

Swap(0, 1) => {4, 1, 2, 0, 3}
Swap(0, 3) => {4, 1, 2, 3, 0}
Swap(0, 4) => {0, 1, 2, 3, 4}

Now you are asked to find the minimum number of swaps need to sort the given permutation of the first N nonnegative integers.

Input Specification:

Each input file contains one test case, which gives a positive N (<=105) followed by a permutation sequence of {0, 1, ..., N-1}. All the numbers in a line are separated by a space.

Output Specification:

For each case, simply print in a line the minimum number of swaps need to sort the given permutation.

Sample Input:
10 3 5 7 2 6 4 9 0 8 1
Sample Output:
9

提交代码

思路:将序列转换为图,形成键-值关系

例如样例:3 5 7 2 6 4 9 0 8 1

对应的值:0 1 2 3 4 5 6 7 8 9

对应的键:3 5 7 2 6 4 9 0 8 1

发现3类环:

a.元素个数>1,包含0的环:0-7-2-3-0

b.元素个数>1,不包含0的环:1-9-6-4-5-1

c.元素个数==1的环:8

其实一张图无非也就最多存在上述3类环。

对于a:交换次数=环的元素个数-1

对于b:交换次数=环的元素个数+1

对于c:交换次数=0

所以,只要统计元素个数>1的环的情况即可。然后根据这些元素个数>1的环是否包含元素0来计算总的交换次数。

代码如下:

 1 #include<cstdio>
 2 #include<stack>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<stack>
 6 #include<set>
 7 #include<map>
 8 using namespace std;
 9 map<int,int> ha;
10 bool vis[100005];
11 void DFS(int cur,int s){
12     vis[cur]=true;
13     if(ha[cur]==s){
14         return;
15     }
16     DFS(ha[cur],s);
17 }
18 //统计点的数量>1的环的个数,有0在的换交换次数是个数-1;没有0在的环,交换次数是个数+1
19 int main(){
20     //freopen("D:\INPUT.txt","r",stdin);
21     int count,n;
22     scanf("%d",&n);
23     count=n;
24     int i,num;
25     for(i=0;i<n;i++){
26         scanf("%d",&num);
27         if(num==i){//去掉元素个数为0的环,剩下的元素个数
28             vis[num]=true;
29             count--;
30         }
31         ha[num]=i;
32     }
33     //剩下的环除了包含元素0的环,其他环的交换次数=环自身元素个数+1
34     for(i=0;i<n;i++){
35         if(!vis[i]){
36             DFS(i,i);
37             count++;
38         }
39     }
40     if(ha[0]!=0){//如果0不单独成环,说明有元素个数>1的环包含0,则这个环在34行时多加了2,这里减去
41         count-=2;
42     }
43     printf("%d
",count);
44     return 0;
45 }
原文地址:https://www.cnblogs.com/Deribs4/p/4780286.html