模拟磁盘碎片整理,写的晕了~
方法:能移就移,不然处理其所在链或环
#include <iostream>
using namespace std;
int v[10010],id[10010],m,n,k,tot,x,r;
bool loop,f;
int main() {
while (~scanf("%d%d",&m,&n)) {
tot = 0;
memset(v,0,sizeof(v));
for (int i=1;i<=n;i++) {
scanf("%d",&k);
for (int j=1;j<=k;j++) {
scanf("%d",&x);
v[x] = ++tot;
id[tot] = x;
}
}
f = true;
for (int i=1;i<=m;i++) {
if (v[i]>0 && v[v[i]]==0) {
printf("%d %d\n",i,v[i]);
f = false;
v[v[i]] = -1;
v[i] = 0;
}
if (v[i]>0 && v[v[i]]>=0) {
k = i;
loop = true;
while (v[k]!=i) {
if (v[k]==0) {
loop = false;
break;
}
k = v[k];
}
if (!loop) {
k = id[k];
while (1) {
printf("%d %d\n",k,v[k]);
f = false;
v[v[k]] = -1;
k = id[k];
if (id[k]==0) {
printf("%d %d\n",k,v[k]);
f = false;
v[v[k]] = -1;
v[k] = 0;
break;
}
}
}
else {
if (v[k]==k) continue;
f = false;
for (r=m;r>=0;r--)
if (v[r]==0) break;
printf("%d %d\n",k,r);
v[r] = v[k];
v[k] = 0;
id[v[r]] = r;
k = id[k];
while (1) {
printf("%d %d\n",k,v[k]);
v[v[k]] = -1;
k = id[k];
if (id[k]==0) {
printf("%d %d\n",k,v[k]);
v[v[k]] = -1;
v[k] = 0;
break;
}
}
}
}
}
if (f) printf("No optimization needed\n");
}
return 0;
}