11292: 【原1292】easy
题目
题目描述
author: 王立力 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1292
Description
简单的题不一定有简单的数据。有n个位置和n个数,初始时每个位置上都放有一个数。我们可以不断的交换两个不同位置上的数,直到达到终止状态。
终止状态指:每个位置上的数都和位置一样,即i号位上的数是i。
同时我们假设进行一次交换用的时间为1,每个单位时间可以对任意对数进行交换操作,但不能对一个数进行两次交换。例如在1的时间里,我们可以交换1跟2、3跟4、5跟6⋯⋯ 但不能交换1跟2、2跟3
求:
1.到达终止状态最少经过几次交换
2.到达终止状态最少需要的时间
Input Format
每个测试点由10组以内数据组成,每组数据由两行组成
第一行:一个整数n,n<=1000000
第二行:n个整数,第i个整数a[i]表示第i个位置上的数是a[i] 1<=a[i]<=n
Output Format
对于每组数据输出两行,每行一个整数。分别是问题1和2的答案
Sample Input
2
2 1
2
2 1
Sample Output
1
1
1
1
q4x3's solution
/**
* 模拟(数学题?)
* 先找环
* 交换次数: 所有环交换次数相加
* 交换时间: 长度为一的环0,长度
* 为二的环1,长度大于等于三的环2
**/
#include <iostream>
using namespace std;
int n, d[1000233], flag[1000233];
int ans1, ans2;
int main() {
while(cin >> n) {
ans1 = 0; ans2 = 0;
for(int i = 1;i <= n;++ i) {
cin >> d[i];
if(d[i] == i) flag[i] = 1;
if(d[i] != i) flag[i] = 0;
}
for(int i = 1;i <= n;++ i) {
if(flag[i]) continue;
int j = d[i], cnt = 0;
while(j != i) {
flag[j] = 1;
j = d[j];
++ cnt;
}
ans1 += cnt;
if(cnt > 1) ans2 = 2;
if(cnt == 1 && ans2 != 2) ans2 = 1;
}
cout << ans1 << endl << ans2 << endl;
}
}
victrid's solution
#include <iostream>
using namespace std;
//Cyka. I'm a blind starcraft player
//I'm a blind starcraft player
//I'm a blind starcraft player
inline int swapi(int& i, int& j) {
int temp = i;
i = j;
j = temp;
return 0;
}
int main() {
int numbers;
int maxround[10] = {0};
int totalsteps[10] = {0};
int groupcount = 0;
while (~scanf("%d", &numbers)) {
int* ff = new int[numbers + 1];
maxround[groupcount] = 0;
for (int i = 1; i <= numbers; i++)
cin >> ff[i];
for (int i = 1; i <= numbers; i++) {
if (ff[i] != i) {
int round = 0;
//looping
int tws1 = i, tws2;
while (true) {
for (tws2 = i; ff[tws2] != tws1; tws2++)
;
swap(ff[tws1], ff[tws2]);
totalsteps[groupcount]++;
round++;
if (round > 2)
round = 2;
if (ff[tws2] == tws2) {
maxround[groupcount] = maxround[groupcount] > round ? maxround[groupcount] : round;
break;
}
tws1 = tws2;
}
}
}
groupcount++;
}
for (int i = 0; i < groupcount; i++) {
if (i)
cout << endl;
cout << totalsteps[i] << endl
<< maxround[i];
}
return 0;
}
zqy2018's solution
/*
See the solution at https://github.com/zqy1018/sjtu_oj_solutions/blob/master/solutions/sjtu1292.pdf
*/
#include <bits/stdc++.h>
#define INF 2000000000
using namespace std;
typedef long long ll;
int read(){
int f = 1, x = 0;
char c = getchar();
while(c < '0' || c > '9'){if(c == '-') f = -f; c = getchar();}
while(c >= '0' && c <= '9')x = x * 10 + c - '0', c = getchar();
return f * x;
}
int n, a[1000005];
bool vis[1000005];
void init(){
for (int i = 1; i <= n; ++i)
a[i] = read();
memset(vis, 0, sizeof(vis));
}
void solve(){
int tm = 0, maxi = 0;
for (int i = 1; i <= n; ++i){
if (vis[i] || i == a[i]) continue;
int t = a[i], cnt = 1;
vis[i] = true;
while (t != i)
vis[t] = true, t = a[t], ++cnt;
maxi = max(maxi, (cnt == 2 ? 1: 2));
tm += (cnt == 2 ? 1: cnt - 1);
}
printf("%d\n%d\n", tm, maxi);
}
int main(){
while (scanf("%d", &n) == 1){
init();
solve();
}
return 0;
}