130 条题解
-
0xcjzj LV 3 @ 2006-09-26 17:18:47
每组数据确定两组相对位置关系,并且这两组互为镜像。
对于某一种排列方式,不在需要位置上的人数即为当前状态到目标状态的最小代价。
先找出其中一种排列方式。由于目标状态可以通过旋转而使得部分人的变化次数减少,所以找出每个人通过某一固定方向旋转到达目标位置的旋转次数。找到某一次数,使得拥有这个次数的人数最多。那么,通过旋转这一最多人拥有的次数,即可使得尽可能多的人不通过交换直接到达目标位置。于是,不拥有这一旋转次数的人数即为这一状态下的最小代价。
然后,用现在的目标状态找出其镜像状态,并且用上述方法再找一遍最小代价,与前面的结果比较,较小值即为答案。
另外,题目中会出现一些无解的情况:
1.某个人被“要”的次数多于两次,也就是说有多于两个的人想要与他(她)邻座,那么无解。
2.根据要求得出的目标状态为多于一个的环,也无解。 -
02006-07-28 17:27:36@
提交了若干次……残念……
-
02006-07-28 16:26:28@
这题比赛时真有人ac?
真不好想
为什么得开longint啊? -
02006-07-25 13:29:56@
排列本质不同的只有二种 正着和反着的
检验几个人不在位置上用数学方法:)模拟法超时的 -
02006-07-23 04:37:47@
注意别误解题意 b1,b2....bm并不指连续位置上的数
-
02006-01-26 09:21:51@
可以用群论证明:如果有k个人不在自己的位置上,那么要且仅要k的代价,即可使这些人归位
剩下的..很简单了吧...
-
-12015-09-12 23:20:54@
qiadafei
Vijos 已自动进入夜间模式。关闭夜间模式(仅本次会话有效)
当前位置:/home/题库/P1008 篝火晚会/题解个人通过/递交:0/1(0%)
未递交
篝火晚会
发表题解需要更丰富的内容输出?编辑器快速入门 | Markdown详细帮助[Ctrl+Enter] 预览
0
回复 liuhehe发表于2015-07-31 20:10
include<iostream> include<cstdio> include<cstring> include<cstdlib>
using namespace std;
const int maxn=50005;
int f[maxn];
int wz[maxn];
int py[maxn][2];
int numn;
void dfs(int cur,int now)
{
if(wz[py[now][1]]==-1)
{
wz[py[now][1]]=(cur+1)%numn;
f[cur+1]=py[now][1];
dfs(cur+1,py[now][1]);
}
else if(wz[py[now][0]]==-1)
{
wz[py[now][0]]=(cur+1)%numn;
f[cur+1]=py[now][0];
dfs(cur+1,py[now][0]);
}
else if(cur==numn-1)return;
else {printf("-1\n");exit(0);}
}
void work()
{
int c1[maxn],c2[maxn];
memset(c1,0,sizeof(c1));
memset(c2,0,sizeof(c2));
for(int i=0;i<numn;i++)
{
c1[(numn+i-f[i]+1)%numn]++;
c2[(numn+i+f[i]-1)%numn]++;
}
int maxx=-1;
for(int i=0;i<numn;i++)
{
maxx=max(maxx,c1[i]);
maxx=max(maxx,c2[i]);
}
printf("%d\n",numn-maxx);
}
int main()
{
scanf("%d",&numn);
memset(wz,-1,sizeof(wz));
for(int i=1;i<=numn;i++)scanf("%d%d",&py[i][0],&py[i][1]);
f[0]=1;wz[1]=0;
dfs(0,1);
for(int i=0;i<numn;i++)
{
// printf("%d ",f[i]);printf("\n");
if(!(f[(i+numn-1)%numn]==py[f[i]][0]||f[(i+numn-1)%numn]==py[f[i]][1]))
{
printf("-1\n");exit(0);
}
if(!(f[(i+numn+1)%numn]==py[f[i]][0]||f[(i+numn+1)%numn]==py[f[i]][1]))
{
printf("-1\n");exit(0);
}
}
work();
return 0;
}
看了半天题解才搞会。。。关键是题目说的很含糊!!!
主要就是先根据每个人要求建环
然后定一个人原地不动,剩下的人做调整,这里有n种情况
接着每种情况可以通过简单的优化通过O(1)时间算出代价0
回复 whxc049发表于2015-07-05 11:02
0
回复 yingjiangyu发表于2015-02-15 21:55
打‘Wrong!’有50分。。
0
回复 东大微雕发表于2015-02-07 15:20
这道题真是太好了。奇妙无穷。
include<iostream> include<string.h> include<stdio.h>
using namespace std;
int a[50005];
int size;
void go(){
int i, j;
int ans = 0;
int dis[50005];
memset(dis, 0, sizeof(dis));
for (i = 1; i <= size; i++){
int d = (a[i] - i + size) % size;
dis[d]++;
}
for (i = 0; i < size; i++){
if (ans < dis[i])
ans = dis[i];
}
memset(dis, 0, sizeof(dis));
for (i = 1; i <= size; i++){
int d = (a[size+1-i]-i+size) % size;
dis[d]++;
}
for (i = 0; i < size; i++){
if (ans < dis[i])ans = dis[i];
}
cout << size-ans << endl;
}
int main(){
freopen("in.txt", "r", stdin);
int neibor[50005][2];
int i;
cin >> size;
for (i = 1; i <= size; i++){
scanf("%d%d",&neibor[i][0],& neibor[i][1]);
}
bool used[50005];
memset(used, 0, sizeof(used));
a[1] = 1;
used[1] = true;
for (i = 2; i <= size; i++){
int last = a[i - 1];
if (!used[neibor[last][0]]){
a[i] = neibor[last][0];
used[a[i]] = true;
}
else if (!used[neibor[last][1]]){
a[i] = neibor[last][1];
used[a[i]] = true;
}
else {
cout << -1 << endl;
return 0;
}
}
if (neibor[1][0] != a[size] && neibor[1][1] != a[size]){
cout << -1 << endl;
return 0;
}
go();
return 0;
}
0
回复 3516发表于2014-07-30 08:59
include<stdio.h>
include<string.h>
int data[50001][2],shi[50001],a[50001];
int main()
{
int n,i,j,qian,hou; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d%d",&data[i][0],&data[i][1]); } a[1]=1;shi[a[1]]=1 for(i=2;i<=n;i++) { qian=data[a[i-1]][0]; hou=data[a[i-1]][1]; if(shi[qian]==0) { a[i]=qian; shi[qian]=1; } else if(shi[hou]==0) { a[i]=hou; shi[hou]=1; } else { printf("-1"); return 0; } } int temp=0,max=0; memset(shi,0,sizeof(shi)); for(i=1;i<=n;i++) { temp=(n+a[i]-i+1)%n; shi[temp]++; } for(i=0;i<n;i++) { if(max<shi[i]) { max=shi[i]; } } memset(shi,0,sizeof(shi)); for(i=1;i<=n;i++) { temp=(n+a[n-i+1]-i+1)%n; shi[temp]++;
}
for(i=0;i<n;i++)
{
if(max<shi[i])max=shi[i];
}
printf("%d",n-max);
}
0
回复 S.Y.F发表于2013-08-31 14:04
题解
1111111129回复于2014-08-13 11:52
orzorzorz
0
回复 S.Y.F发表于2013-07-29 16:55
从10、到30、到100。。。。。。
题解:http://blog.163.com/syf_light_feather/blog/static/223755067201362945326756/
0
回复 vcvycy发表于2013-06-30 00:56
20 30 40 50 70 分都有~泪流满面.
Accepted
100
772 2
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:55:05
Wrong Answer
70
613 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:53:24
Wrong Answer
70
686 2
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:45:35
Wrong Answer
70
856 2
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:42:12
Wrong Answer
70
803 2
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:37:26
Wrong Answer
70
882 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:22:39
Wrong Answer
70
1145 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:20:30
Wrong Answer
10
733 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:11:30
Wrong Answer
50
723 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:04:20
Wrong Answer
50
781 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:55:49
Wrong Answer
40
656 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:49:49
Wrong Answer
40
758 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:44:00
Time Exceeded
30
7160 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:38:22
Time Exceeded
20
7135 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:35:08
0
回复 SEX丶Elope发表于2013-02-16 10:10
点击查看程序源码+详细题解
cuichen回复于2014-09-09 09:24
怎么又是你??你有什么企图?骗访问量???垃圾!
0
回复 qyjubriskxp发表于2010-07-09 21:31
再一次体会到c++流的悲剧,秒杀和3s原来只是输入方式的不同,杯具~~
yuyilahanbao回复于2014-01-24 11:47
从c转到c++第一次不AC(除去忘记把语言有c改为c++的)就是因为c++输入输出的问题
从那次起,我的c++的输入都是用scanf和printf了
因为
保险
安全
我记不清cin是<<还是>>
printf和scanf相对更灵活
....
0
回复 slm发表于2010-03-16 18:27
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
嘿嘿
0
回复 superyoi发表于2009-11-10 11:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
superyoi killed p1008 with a headshot by awp
0
回复 200853349发表于2009-11-10 10:49
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
当我看到众位神牛打出“置换群”三个字后,我在黑书百度GOOGLE维基百科逛了得有一个半小时多然后回来AC了。。。
思路和strini神牛的基本一样。
0
回复 sinb发表于2009-11-09 13:02
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
其实很简单,不要想复杂了,先是想办法构成,然后用置换群的方法即可ac。
0
回复 香蕉派发表于2009-11-06 11:29
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
虽然不懂什么叫置换群,但是思路还是很清晰的。。
0
回复 赏金神侠PPF发表于2009-11-05 11:45
一星星纪念~
0
回复 strini发表于2009-10-30 22:11
根据群论原理,任何置换群都可以分解为若干个循环节。显然,这道题目就是冲着这点来的。因为如果某循环的长度为L,那么本题中只需要代价为L的操作。注意,这里的L!=1,这是因为只有一个人的循环节不需要任何代价的操作。到这里才只能拿三十分,因为圈是可以旋转的,常规方法需要O(n^2)才能解决。不妨这里以编号为1的人为基准,定义每个人到自己应该所在位置的距离。距离不超过n-1。可以通过最大值来寻找能在自己位置上的最多的人数(因为距离为x的人在旋转x次后转到自己的位置上),那么在比较好的情况下,可以优化到O(n)。
TIME: 1H
SUBMIT:
1 70 Error: 发现希望相邻是不精确的,于是改了个搜索方向。(以为题目给定的是按照左右方向,白书说过不能“假定”!)。
2 90 Error: 终于明白要取两个搜索方向的最大值。
3 Accepted.
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 skykey发表于2009-10-29 17:58
include<iostream>
using namespace std;
int n;
int a[50001],b[50001],c[50001];
int aim[50001];
void G_MAP()
{
bool mark[50001]={false};
int p=1,r=1;
while(p<=n)
{
aim[p]=r;mark[r]=true;p++;
if(!mark[a[r]])r=a[r];
else if(!mark[b[r]])r=b[r];
else if(p<=n){cout<<-1;exit(0);}
}
}
int COMPULATE()
{
int max=0;
int t;
int record[2][50001];
for(int i=1;i<=n;i++)record[0][i]=record[1][i]=0;
for(int i=1;i<=n;i++)
{
if((t=aim[i]-i)<0)t+=n; record[0][t]++; if(record[0][t]>max)max=record[0][t];
if((t=aim[i]-(n+1-i))<0)t+=n; record[1][t]++; if (record[1][t]>max)max=record[1][t];
}
return max;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{scanf("%d%d",&a[i],&b[i]);c[a[i]]++;c[b[i]]++;}
for(int i=1;i<=n;i++)if(c[i]!=2){cout<<-1;return 0;}
G_MAP();
int T=COMPULATE();
cout<<n-T;
}
0
回复 song19931218发表于2009-10-27 20:11
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
考虑两种情形(貌似这两种情形很像,但又真的不同,后来才想起,在化学的手性碳原子那部分遇到过类似情况。。。)
然后就是运用置换群的知识
0
回复 Aries_C发表于2009-10-25 08:24
正反两遍...两遍...<幽幽的声音飘远..>
不然就是70分啊...
不看题解的情况下竟然自己想到了...
记得以前老师给我们做过这题的..细节什么的现在做又忘记了..唉..
0
回复 国防安全员001发表于2009-10-21 22:00
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1701人
提交 4835次
通过率 35%
难度 3
题目表述有问题。。
0
回复 liubosen发表于2009-10-21 21:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
yaaaayyayayyayayayayayayayayayayayayayayayyaayayayayayayyaayayayay
var
n,max,i:longint;
a,b,c,d:array[0..50001] of longint;
begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
c[1]:=1;
c[2]:=a[1];
for i:=3 to n do
if c=a[c] then c[i]:=b[c]
else
if c=b[c] then c[i]:=a[c]
else begin
writeln(-1);
halt
end;
if c[n]<>b[1] then
begin
writeln(-1);
halt
end;
fillchar(d,sizeof(d),0);
for i:=1 to n do
inc(d[(c[i]-i+n)mod n]);
for i:=0 to n-1 do
if d[i]>max then max:=d[i];
fillchar(d,sizeof(d),0);
for i:=1 to n do
inc(d[(c[i]+i-1)mod n]);
for i:=0 to n-1 do
if d[i]>max then max:=d[i];
writeln(n-max);
end.
0
回复 lishunzhi发表于2009-10-21 00:11
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
置换群,但建环是重点
0
回复 zebra发表于2009-10-03 09:48
include <iostream> include <cassert>
using namespace std;
long N,seq[50001],p=1;
class
{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2)
{
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2)
return true;
return false;
}
public:
bool AddE(long v1,long v2)
{
if(isnbr(v1,v2))
return true;
else
if(nbr[v1][0]==2||nbr[v2][0]==2)
return false;
else
{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i)
{
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++)
{
if(!flag[nbr[i][j]])
{
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve()
{
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N; b=seq[i]-(N+1-i); if(b<0) b+=N; if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main()
{
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++)
{
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2))
{
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
system("pause");
return 0;
}
0
回复 -117-Join发表于2009-09-18 21:29
哪位大牛帮忙看看我错哪里了
它只得90分
program fire;
type
arr=record
l,r:longint;
end;
var
num:array[1..50000]of longint;
a:array[1..50000]of arr;
b:array[1..50000]of longint;
i,k,j,n:longint;
begin
readln(n);
for i:=1 to n do
readln(a[i].l,a[i].r);
b[1]:=1;
b[n]:=a[1].l;
if a[b[n]].l=b[1]then b[n-1]:=a[b[n]].r
else b[n-1]:=a[b[n]].l;
i:=n-1;
b[2]:=a[1].r;
j:=2;
while j<=i do
begin
if b<>a[b[i]].l then b:=a[b[i]].l
else b:=a[b[i]].r;
dec(i);
if b[j-1]<>a[b[j]].r then b[j+1]:=a[b[j]].r
else b[j+1]:=a[b[j]].l;
inc(j);
end;
for i:=2 to n-1 do
if(b<>a[b[i]].r)and(b<>a[b[i]].l)or(b<>a[b[i]].r)and(b<>a[b[i]].l)then
begin
write(-1);
halt
end;
if(b[n]<>a[b[1]].l)and(b[n]<>a[b[1]].r)or(b[2]<>a[b[1]].l)and(b[2]<>a[b[1]].r)or(b[1]<>a[b[n]].l)and(b[1]<>a[b[n]].r)or(b[n-1]<>a[b[n]].l)and(b[n-1]<>a[b[n]].r)then
begin
write(-1);
halt
end;
num[0]:=0;
for i:=1 to n do
begin
a[b[i]].l:=i;
num[i]:=0;
end;
for i:=1 to n do
if a[i].l-i>=0 then inc(num[a[i].l-i])
else inc(num[a[i].l-i+n]);
j:=0;
for i:=0 to n do
if num[i]>j then j:=num[i];
write(n-j);
end.
写的有点长
0
回复 fs302发表于2009-09-17 20:13
分析:学一个好思想:正难则反!由顺序到乱序我们很难快速找到,但是我们知道如何从乱序变为顺序!解决本题利用了组合数学中置换群的思想。
从第一个人处断开,将圆环的问题转化为序列的问题。如果可以,求出目标序列。求出目标序列复杂度O(n).
求出目标序列右移0至n-1位置时,不需要移动的人数。将目标序列反转,再求出目标序列右移0至n-1位置时,不需要移动的人数。求不需要移动的人数最大等价于求需要移动的人数最小。复杂度O(n)。
更详细的说:
引进“相对有序”这个概念,当两个人满足C[j]-C[i]==j-i时,两个相对有序。
题目要求最小的总代价,但是我们可以考虑倒过来想,要求最小的总代价亦即求最多有多少人不用移动,亦即相对有序。
然后我们引进一个辅助变量T=C-I,{C-I>=0},T=C[i]-I+N,{C[i]-I<0},那么这个T[i]有什么意义呢?我们知道初始状态的编号是1-N,而目标状态是C[1]-C[N],那么C-I便是从目标状态到初始状态顺时针所要移动的距离,那么如果那么T值相等的两个同学则是相对有序的,亦即不用移动,我们只要找出最大的T然后N-Max(T)就是得到的结果,但是这样还不够,因为刚刚那样只是顺时针所要移动的距离,我们还要计算逆时针的到的结果,从顺时针和逆时针中找到最大的T,然后N-Max(T)才能够是正确结果.
0
回复 maxint64发表于2009-09-01 21:33
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
先是物理大发了——以为 b1,b2...bm是连续的
看了牛们的题解 一次ac :)
0
回复 柔情使者发表于2009-08-20 15:44
第一遍做的时候没有看题解,自己测了好几遍总是60分,看了n多大牛的解释才恍然大悟,竟然要正反两遍!!!唉,幸亏咱有测试数据,否则我可就惨了...
O(n)的求目标队列算法,都说是冒泡排序,我没看出来,倒是有点像。
0
回复 maxiem发表于2009-08-18 20:55
物理自重啊,嘿嘿。
注意要正反两遍哦~
9MS?
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 9ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:9ms
(好像那个冒泡是口胡,大家不要被那个蒙了
program fire;
var
st:array [1..50000,1..2] of longint;
k,final:array [0..50000] of longint;
ex:array [1..50000] of boolean;
p,max,i,n:longint;
begin
fillchar (st,sizeof(st),0);
fillchar (ex,sizeof(ex),0);
fillchar (final,sizeof(final),0);
fillchar (k,sizeof(k),0);
readln (n);
for i:=1 to n do readln (st,st);
final[1]:=1;p:=2;ex[1]:=true;
for i:=1 to n do begin
if ex[st[final[i],1]]=false then begin
final[p]:=st[final[i],1];
ex[st[final[i],1]]:=true;
inc(p);
end
else if ex[st[final[i],2]]=false then begin
final[p]:=st[final[i],2];
ex[st[final[i],2]]:=true;
inc(p);
end;
end;
if p-1<>n then begin
writeln (-1);
halt;
end;
max:=0;
for i:=1 to n do if final[i]>=i then inc(k[final[i]-i]) else inc(k[n-i+final[i]]);
for i:=0 to n-1 do if k[i]>max then max:=k[i];
fillchar (k,sizeof(k),0);
for i:=n downto 1 do if final[i]>=n-i+1 then inc(k[final[i]-n+i-1]) else inc(k[final[i]+i-1]);
for i:=0 to n -1 do if k[i]>max then max:=k[i];
writeln (n-max);
end.
0
回复 suning发表于2009-08-14 09:43
啊呜~
一年前误解了题意~
一年后理解了题意~
然后就是1次美妙的AC
PS:[误]解[理]解~~~[物理]?
0
回复 fengwuliu发表于2009-08-13 17:20
lgxcgd说的太对了!太感谢了5555
0
回复 Matt发表于2009-08-11 22:28
NOIP也会考高等数学...
由于原图是环,所以置换群可表示为一次循环。作差是个好方法。
但求冒泡排序是怎么作的
0
回复 3830372发表于2009-08-11 21:28
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1504人
提交 4282次
通过率 35%
难度 3
提交 讨论 题解 状态
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 尖端才子发表于2009-08-11 11:14
纪念一下……第1500个AC……
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1500人
提交 4274次
通过率 35%
难度 3
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 SecretAgent发表于2009-08-10 14:02
置换群是正解
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 yangbei发表于2009-08-07 14:57
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 338ms
├ 测试数据 05:答案正确... 322ms
├ 测试数据 06:答案正确... 306ms
├ 测试数据 07:答案正确... 338ms
├ 测试数据 08:答案正确... 338ms
├ 测试数据 09:答案正确... 322ms
├ 测试数据 10:答案正确... 306ms
Accepted 有效得分:100 有效耗时:2270ms
算镜像时偷了点懒,不过也算一遍AC了
0
回复 ja_son发表于2009-08-06 15:44
a:拆环成队,寻求目标队列。
b:b1,b2...bm不是连续的,而且是任意的。只要有成立目标队列,与原来的队列相匹配就可以知道有多少(设为n个)需要移动位置,则代价就是n。
c:目标队列有多种情况,可以反转,也可以左右移动。
0
回复 1s发表于2009-08-03 17:56
如对本题有疑问可以参看我的题解:
http://xujieqi.blog.hexun.com/35722312_d.html
0
回复 DMKaplony发表于2009-07-30 15:15
当时的时间限制好像是2s。。有个题解说把1定为第一项然后进行冒泡排序。。不过这里是1s 啊。。。也行只有置换群了吧。
0
回复 xusc_2009发表于2009-07-28 14:30
看不懂,只好搁浅
什么时候想清楚了再做
0
回复 董发表于2009-07-24 19:11
program p1008;
var i,n,k,j,sum1,sum2,ans,max:longint;
a,b,w,d,c:array[0..50005] of longint;
begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
w[1]:=1; w[2]:=a[w[1]];
k:=1;
repeat
inc(k);
if w[k-1]=a[w[k]] then w[k+1]:=b[w[k]]
else if w[k-1]=b[w[k]] then w[k+1]:=a[w[k]]
else begin
writeln(-1);
exit;
end;
until k=n;
if w[n+1]<>w[1] then
begin
writeln(-1);
exit;
end;
for i:=1 to n do
begin
a[i]:=w[i]-i;
b[i]:=w[n-i+1]-i;
if a[i]<0 then a[i]:=a[i]+n;
if b[i]<0 then b[i]:=b[i]+n;
inc(c[a[i]]);
inc(d[b[i]]);
end;
for i:=0 to n-1 do
begin
if ans<c[i] then ans:=c[i];
if ans<d[i] then ans:=d[i];
end;
writeln(n-ans);
end.
0
回复 我飞发表于2009-07-23 21:00
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 93狒狒发表于2009-07-23 20:59
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
秒杀......
0
回复 fjxmlhx发表于2009-07-22 13:15
置换群,做2n次,顺时针和逆时针.
对于一个置换,最小操作费用是所有循环长度的和.因此实际上是找出2n个置换中哪个置换循环长度为1的数量最多.
0
回复 340508965发表于2009-07-21 15:01
⊙﹏⊙b汗
不知道的以为这是数学竞赛......
...
我的数论与图论可以说脑袋里空白一片.........
怎么办,我的竞赛啊
........
算了 看了题解 大家写的
总算弄懂这道题了
先前以为b1,b2,b3..bm是连续的
没想到是任意的!!!!!!!!!
诶 叹悲歌未切 为撼奈何编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
总算AC了
program p1008;
var i,n,k,j,sum1,sum2,ans,max:longint;
a,b,w,d,c:array[0..50005] of longint;
begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
w[1]:=1; w[2]:=a[w[1]];
k:=1;
repeat
inc(k);
if w[k-1]=a[w[k]] then w[k+1]:=b[w[k]]
else if w[k-1]=b[w[k]] then w[k+1]:=a[w[k]]
else begin
writeln(-1);
exit;
end;
until k=n;
if w[n+1]<>w[1] then
begin
writeln(-1);
exit;
end;
for i:=1 to n do
begin
a[i]:=w[i]-i;
b[i]:=w[n-i+1]-i;
if a[i]<0 then a[i]:=a[i]+n;
if b[i]<0 then b[i]:=b[i]+n;
inc(c[a[i]]);
inc(d[b[i]]);
end;
for i:=0 to n-1 do
begin
if ans<c[i] then ans:=c[i];
if ans<d[i] then ans:=d[i];
end;
writeln(n-ans);
end.
0
回复 zsy90943发表于2009-07-18 00:51
构造巧妙、、看来还是要学好数论和图论额、、、、
0
回复 POM无敌牛B发表于2009-07-16 11:47
编译通过...
├ 测试数据 01:运行超时...
├ 测试数据 02:运行超时...
├ 测试数据 03:运行超时...
├ 测试数据 04:运行超时...
├ 测试数据 05:运行超时...
├ 测试数据 06:运行超时...
├ 测试数据 07:运行超时...
├ 测试数据 08:运行超时...
├ 测试数据 09:运行超时...
├ 测试数据 10:运行超时...
Unaccepted 有效得分:0 有效耗时:0ms
无奈 哪位哥哥救救我
0
回复 yxy发表于2009-06-16 18:16
把置换解释成度为2图,真有才.
求出序列,正反分别做一次差就行了.
0
回复 sxpeter发表于2009-06-14 16:56
讲建环吧。数组w表示环,我用的是一种类似并查集的方法。
begin
read(n);
for i:=1 to n do read(a[i],b[i]);
t:=2;w[1]:=1;w[2]:=a[1];
while true do begin
if a[w[t]]<>w[t-1]then w[t+1]:=a[w[t]]//是否在左边
else if b[w[t]]<>w[t-1]then w[t+1]:=b[w[t]]//是否在右边
else begin writeln(-1);halt;end;//失败判断
inc(t);
if t>n then break;
end;
if w[n+1]<>w[1]then begin writeln(-1);halt;end;//本句一定要加!!!!!!
end.
0
回复 lgxcgd发表于2009-05-17 20:24
首先把这个圈看做一个图,每个同学看做一个顶点。因为要形成环,所以每个顶点的度必须为2。
如果存在度数不为2的顶点,那么整个图无法构成一个环,即“无论怎么调整都不能符合每个同学的愿望”输出-1。
如果是一个环,那么就遍历图,生成以第1个顶点为开头的序列。现在就要求出最小移动的代价。
在理解题意所述的调整方式中,要注意实际上就是把M个在错误位置上的人移动到正确的位置上,代价为M。一次下令移动即可。
假如生成的目标序列为1,5,3,2,4。我们现在就需要比较它和初始状态1,2,3,4,5,看有几个人离开了原来的位置。但这个序列实际代表的是一个环,而且方向正反有两种,就需要把初始序列正反分别转N次,和得到的序列比较,看其中最少有几个位置上的人编号不相同,就得到了我们要求的最小代价。
上述方法有大量冗余。但可以发现转来转去不管怎么转,任意两个人之间的相对位置关系在这过程中都不会变。于是想到做差,如果差小于0则加上N。
1 5 3 2 4
- 1 2 3 4 5
0 3 0 3 4
这表示序列1,5,3,2,4不转动时1,3两个人在原来的位置上,转动3个位置后5和2两个人在原来的位置上,转动4个位置后只有4一个人会在原来的位置上。这就是说,1,5,3,2,4与1,2,3,4,5在旋转后最多有2个位置上的人编号相同,即最少有3个位置上的人编号不相同。同理要反转再求一次。
记录每个不同的差值的个数,取其最大值P,即不调换次数最大的。结果N-P就是调换次数最小的。
0
回复 src250发表于2009-05-14 08:27
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
切记:重新构图时一定要对数组清空!我的第一次只有50分,就是这个原因!
0
回复 love19960108发表于2009-04-26 17:59
这题可以用C++这样做么??
include <iostream> include <cassert>
using namespace std;
long N,seq[50001],p=1;
class{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2){
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2) return true;
return false;
}
public:
bool AddE(long v1,long v2){
if(isnbr(v1,v2)) return true;
else if(nbr[v1][0]==2||nbr[v2][0]==2) return false;
else{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i){
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++){
if(!flag[nbr[i][j]]){
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve(){
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N; b=seq[i]-(N+1-i); if(b<0) b+=N; if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main(){
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++){
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2)){
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
return 0;
}
0
回复 voyagec2发表于2009-03-18 15:53
难理解,不过算法很精妙
0
回复 pRoevollove发表于2009-02-25 23:49
天,把(p[i]-i+n)mod n理所当然地打成了abs(p[i]-i)
结果一直50分……还一直以为自己构造错了……
ps 我可以过楼下的范例哦
0
回复 ufo172849z发表于2009-01-24 23:05
ms楼下的程序不能处理这种反例(测试数据还是不够强啊)
6
2 3
1 3
1 2
5 6
4 6
4 5
应该输出-1的吧?因为是两个环
var a,b:array[0..50000]of longint;
c:array[0..50000,1..2]of longint;
d:array[0..50000]of boolean;
i,j,k,m,n,max:longint;
can:boolean;
begin
readln(n);
for i:=1 to n do
readln(c,c);
b[0]:=c[1,1]; b[n]:=c[1,1];
fillchar(d,sizeof(d),0);
k:=1;
can:=true;
for i:=1 to n-1 do
begin
if d[k] then can:=false;
b[i]:=k; d[k]:=true;
if b=c[k,1] then k:=c[k,2]
else if b=c[k,2] then k:=c[k,1]
else can:=false;
if not can then break;
end;
if can then
if b[n]<>k then can:=false;
if can then
begin
max:=-1;
fillchar(a,sizeof(a),0);
for i:=1 to n do
inc(a[(b[i]-i+n) mod n]);
for i:=0 to n-1 do
if a[i]>max then max:=a[i];
fillchar(a,sizeof(a),0);
for i:=1 to n do
inc(a[(b[n-i+1]-i+n)mod n]);
for i:=1 to n-1 do
if a[i]>max then max:=a[i];
writeln(n-max);
end
else
writeln(-1);
end.
0
回复 tangdongjian发表于2009-01-23 22:17
我在做镜像时把原先max直接覆盖上了,注意
0
回复 永恒888发表于2009-10-26 22:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 tangkunjie发表于2009-06-04 19:50
挺烦人的题目
0
回复 ykspeter发表于2008-11-13 20:32
program fire(input,output);
var
n,i,j,k,max,v:longint;
a:array[0..100000,1..2] of longint;
b,c:array[0..100000] of longint;
begin
readln(n);
for i:=1 to n do readln(a,a);
for i:=1 to n do
begin
k:=0;
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if (k=4) or (k=3)
then begin
writeln('-1');
exit
end
end;
b[1]:=1;i:=2;k:=a[1,1];j:=1;
repeat
b[i]:=k;
inc(i);
v:=k;
if a[k,1]<>j
then k:=a[k,1]
else k:=a[k,2];
j:=v;
until i=n+1;
fillchar(c,sizeof(c),0);
for i:=1 to n do inc(c[(b[i]-i+n)mod n]);
for i:=0 to n-1 do
if c[i]>max
then max:=c[i];
fillchar(c,sizeof(c),0);max:=0;
for i:=1 to n do inc(c[(b[n-i+1]-i+n)mod n]);
for i:=n-1 downto 0 do
if c[i]>max
then max:=c[i];
writeln(n-max);
end.
0
回复 getuojian发表于2008-11-10 13:38
include<stdio.h> include<memory.h>
const int maxn=50010;
int n;
int f[maxn][2];
int goal[maxn];
int ans=maxn;
int hash[maxn];
bool SET_ORI(){
bool flag[maxn];
memset(flag, true, sizeof(flag));
goal[1]=1; flag[1]=false;
for (int i=1; i<=n-1; i++){
if (flag[f[goal[i]][0]]){
goal=f[goal[i]][0];
flag[f[goal[i]][0]]=false;
continue;
}
if (flag[f[goal[i]][1]]){
goal=f[goal[i]][1];
flag[f[goal[i]][1]]=false;
continue;
}
return false;
}
if ((goal[n]!=f[1][0]) && (goal[n]!=f[1][1]))
return false;
return true;
}
int SWAP(int i, int j){
int t=goal[i];
goal[i]=goal[j];
goal[j]=t;
return 0;
}
int min(int i, int j){
return i>j?j:i;
}
int HASH(){
for(int i=1; i<=n; i++)
hash[i]=goal[i]-i+n;
return 0;
}
int CALC(){
int temp[maxn2], back=0;
memset(temp, 0, sizeof(temp));
for (int i=1; i<=n; i++)
temp[hash[i]%n]++;
for (int i=1; i<=2n-1; i++)
if (temp[i] > back)
back=temp[i];
return back;
}
int main(){
freopen("fire.in", "r", stdin);
freopen("fire.out", "w", stdout);
scanf("%d", &n);
for (int i=1; i<=n; i++)
scanf("%d %d", &f[i][0], &f[i][1]);
if (!SET_ORI()){
printf("-1");
return 0;
}
//forward
HASH();
ans=min(ans, n-CALC());
//backward
for (int i=1; i<=n/2; i++)
SWAP(i,n-i+1);
HASH();
ans=min(ans, n-CALC());
printf("%d", ans);
return 0;
}
0
回复 IVORY发表于2008-11-06 10:46
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
CHEAT的...
0
回复 storey p发表于2008-11-05 14:19
回447389831:
exit换成halt
0
回复 FenXy发表于2008-11-04 08:28
艺术p245
0
回复 hlq发表于2008-11-01 14:31
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
求不在位置上的人数
a【i】 第i位上的同学编号
for i:=1 to n do
begin
inc(b[(a[i]-i+n) mod n])
end;
max:=0;
for i:=0 to n-1 do
if b[i]>max then max:=b[i];
fillchar(b,sizeof(b),0);
for i:=1 to n do
begin
inc(b[(a[i]-(n-i+1)+n)mod n]);//对称
end;
for i:=0 to n-1 do
if b[i]>max then max:=b[i];
0
回复 Will~骷髅发表于2008-10-30 21:37
编译通过...
├ 测试数据 01:运行超时...
├ 测试数据 02:运行超时...
├ 测试数据 03:运行时错误...|错误号: -1073741819
├ 测试数据 04:运行时错误...|错误号: -1073741819
├ 测试数据 05:运行时错误...|错误号: -1073741819
├ 测试数据 06:运行时错误...|错误号: -1073741819
├ 测试数据 07:运行时错误...|错误号: -1073741819
├ 测试数据 08:运行时错误...|错误号: -1073741819
├ 测试数据 09:运行时错误...|错误号: -1073741819
├ 测试数据 10:运行时错误...|错误号: -1073741819
Unaccepted 有效得分:0 有效耗时:0ms
怎么会这样???
0
回复 悲伤逆流成河发表于2008-10-28 22:13
include <iostream> include <fstream>
using namespace std ;
int hash[50001];
int n , i , j , t , maxs(0) ;
inline void HASH ( int e[] )
{
for ( i = 1 ; i <= n ; i++ )
{
e[i] -= i ;
if ( e[i] < 0 ) e[i] += n ;
hash[e[i]]++ ;
}
for ( i = 0 ; i < 50001 ; i++ )
if ( maxs < hash[i] ) maxs = hash[i] ;
}
int main(){
ifstream fin ("fire.in") ;
ofstream fout ("fire.out") ;
fin >> n ;
int e[n+1] , h[n+1][2] , e2[n+1];
bool f[n+1] ;
for ( i = 1 ; i <= n ; i++ )
{
f[i] = false ;
fin >> h[i][0] >> h[i][1] ;
}
e[1] = 1 ;
f[1] = true ;
for ( i = 2 ; i <= n ; i++ )
{
if ( e < 0 ) { fout << -1 << endl ; exit(0) ; }
if ( !f [ h[ e ][0] ] ) e[i] = h[ e ][0] ;
if ( !f [ h[ e ][1] ] ) e[i] = h[ e ][1] ;
f[ e[i] ] = true ;
}
for ( i = 1 , j = n ; i <= n ; i++,j-- ) e2[j] = e[i] ;
HASH ( e ) ;
memset ( hash , 0 , sizeof ( hash ) ) ;
HASH ( e2 ) ;
fout << n - maxs << endl ;
}
0
回复 evelynhe发表于2008-10-26 16:31
“置换群思想...今天刚明白...
先构造新数列(要构造两次,否则只有70分),然后向右计算相对位置差,然后累加记录数组,然后用N减去相对位置差累加值最大的,就是答案... ”
这是真的
0
回复 true1023发表于2008-10-25 09:32
置换群的基本概念
利用原序列和目标序列每个元素的绝对位置差来求出原序列每个元素对于目标序列的相对位置,找相对位置相同的最多的元素数,用总元素数减去它即为结果。
0
回复 447389831发表于2008-10-21 09:45
program fire(input,output);
var
n,i,j,k,max,v:longint;
a:array[0..100000,1..2] of longint;
b,c:array[0..100000] of longint;
begin
readln(n);
for i:=1 to n do readln(a,a);
for i:=1 to n do
begin
k:=0;
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if (k=4) or (k=3)
then begin
writeln('-1');
exit
end
end;
b[1]:=1;i:=2;k:=a[1,1];j:=1;
repeat
b[i]:=k;
inc(i);
v:=k;
if a[k,1]<>j
then k:=a[k,1]
else k:=a[k,2];
j:=v;
until i=n+1;
fillchar(c,sizeof(c),0);
for i:=1 to n do inc(c[(b[i]-i+n)mod n]);
for i:=0 to n-1 do
if c[i]>max
then max:=c[i];
fillchar(c,sizeof(c),0);max:=0;
for i:=1 to n do inc(c[(b[n-i+1]-i+n)mod n]);
for i:=n-1 downto 0 do
if c[i]>max
then max:=c[i];
writeln(n-max);
end.
90 分,牛人门帮看下把
0
回复 cnfnje1发表于2008-10-17 18:12
置换群.....是什么?
readln(n);
for i:=1 to n do readln(a[i],b[i]);
c[1]:=1; c[2]:=a[1];
for i:=3 to n do if c=a[c] then c[i]:=b[c]
else if c=b[c] then c[i]:=a[c]
else begin writeln(-1); halt end;
if c[n]<>b[1] then begin writeln(-1); halt end;
fillchar(d,sizeof(d),0);
for i:=1 to n do inc(d[(c[i]-i+n)mod n]);
for i:=0 to n-1 do if d[i]>m then m:=d[i];
fillchar(d,sizeof(d),0);
for i:=1 to n do inc(d[(c[i]+i-1)mod n]);
for i:=0 to n-1 do if d[i]>m then m:=d[i];
writeln(n-m);
是么?
0
回复 lyrics发表于2008-10-12 19:55
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
技巧性比较强吧,楼下不必构造2次,计算时从头至尾算一次,再倒过来算一次就行了
0
回复 LV.唱响发表于2008-10-05 08:38
置换群思想...今天刚明白...
先构造新数列(要构造两次,否则只有70分),然后向右计算相对位置差,然后累加记录数组,然后用N减去相对位置差累加值最大的,就是答案...
0
回复 宇智波带波斯猫发表于2008-10-05 08:33
Flag Accepted
题号 P1008
类型(?) 其它
通过 1065人
提交 3000次
通过率 35%
难度 3
第3000个提交的
0
回复 鸳鸯羡发表于2008-09-28 18:19
include <iostream>
using namespace std ;
int hash[50001];
int n , i , j , t , maxs(0) ;
inline void HASH ( int e[] )
{
for ( i = 1 ; i <= n ; i++ )
{
e[i] -= i ;
if ( e[i] < 0 ) e[i] += n ;
hash[e[i]]++ ;
}
for ( i = 0 ; i < 50001 ; i++ )
if ( maxs < hash[i] ) maxs = hash[i] ;
}
int main(){
cin >> n ;
int e[n+1] , h[n+1][2] , e2[n+1];
bool f[n+1] ;
for ( i = 1 ; i <= n ; i++ )
{
f[i] = false ;
cin >> h[i][0] >> h[i][1] ;
}
e[1] = 1 ;
f[1] = true ;
for ( i = 2 ; i <= n ; i++ )
{
if ( e < 0 ) { cout << -1 << endl ; exit(0) ; }
if ( !f [ h[ e ][0] ] ) e[i] = h[ e ][0] ;
if ( !f [ h[ e ][1] ] ) e[i] = h[ e ][1] ;
f[ e[i] ] = true ;
}
for ( i = 1 , j = n ; i <= n ; i++,j-- ) e2[j] = e[i] ;
HASH ( e ) ;
memset ( hash , 0 , sizeof ( hash ) ) ;
HASH ( e2 ) ;
cout << n - maxs << endl ;
}
80分
0
回复 月光疾风发表于2008-09-25 13:03
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
纪念我第200次提交!过第79题。。。。
0
回复 ghostplant发表于2008-09-20 19:48
include <iostream> include <fstream> include <cassert>
using namespace std;
long N,seq[50001],p=1;
class{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2){
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2) return true;
return false;
}
public:
bool AddE(long v1,long v2){
if(isnbr(v1,v2)) return true;
else if(nbr[v1][0]==2||nbr[v2][0]==2) return false;
else{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i){
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++){
if(!flag[nbr[i][j]]){
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve(void){
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N; b=seq[i]-(N+1-i); if(b<0) b+=N; if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main(){
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++){
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2)){
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
return 0;
}
0
回复 zzh19950802发表于2008-09-17 19:29
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案错误... ├ 标准行输出
├ 错误行输出
├ 测试数据 05:答案错误... ├ 标准行输出
├ 错误行输出
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 462ms
├ 测试数据 08:答案正确... 369ms
├ 测试数据 09:答案正确... 384ms
├ 测试数据 10:答案错误...程序输出比正确答案长
为什么我的程序不对?
include <iostream>
using namespace std;
define MAXN 50000
int man[MAXN+2][2];
int cercle[MAXN+2]={0,1};
int used[MAXN+2]={0};
int reduce[2][MAXN+2]={0};
int n;
int main()
{
long i,p,q=1,t;
int max=0;
cin>>n;
for (i=1;i<=n;i++) cin>>man[i][0]>>man[i][1];
p=man[q][1];
for (i=2;i<=n+1;i++)
{
if (man[q][1]==p)
{
p=q;
q=man[q][0];
}
else
{
if(man[q][0]!=p) break;
p=q;
q=man[q][1];
}
if(used[q]) break;
else used[q]=1;
cercle[i]=q;
}
if (i<=n+1) cout<<-1;
else
{
for (i=1;i<=n;i++)
{
if((t=cercle[i]-i)<0) t+=n; reduce[0][t]++; if (reduce[0][t]>max) max=reduce[0][t];
if ((t=cercle[i]-n+i-1)<0) t+=n; if (reduce[1][t]>max) max=reduce[1][t];
}
cout<<n-max;
}
return 0;
}
0
回复 liaorc发表于2008-09-16 17:56
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 cxy450090074发表于2008-09-04 13:34
oh no
0
回复 Lost.G发表于2008-08-22 15:49
我在想``怎么样才能不看错这题呢
0
回复 bonism发表于2008-08-14 21:30
时间复杂度O(N)。。。
原来我一直把题意理解错。。。囧!!。。
关于“置换群”,请看LRJ的《算法艺术与信息学竞赛》P245那一小节,还是比较好理解的。
0
回复 lemon_cn发表于2008-08-08 15:55
热烈庆祝用pascal AC的第二题~
p.s.我是C++的~~
0
回复 oipn4e2发表于2008-08-05 21:36
解决效率不高,但AC了。
0
回复 notblack发表于2008-08-01 09:17
用距离来分类,统计在原位的最大人数,奇怪的是
b[1]:=1;
b[2]:=a[1,1];
b[n]:=a[1,2];
建环的时候,上面的改成
b[1]:=1;
b[2]:=a[1,2];
b[n]:=a[1,1];
最后一个点却过不了,太奇怪了.
0
回复 332404521发表于2008-07-14 13:53
对于初三刚刚中考完的我,要理解这题的意思是万万不能的。。。
看题解我知道了应该怎么做,但那不是我的,所以不做了。。。
哪天能证明出来那啥再来做
0
回复 Sheeta发表于2007-11-14 15:45
好简单啊
直接贪啊
(P.S.置换群?什么东东...)
0
回复 mingyueyucai发表于2007-11-09 21:22
我代码写了老长老长,结果还是只过了8个点,有没有搞错?
我想请问一下,我和大家的一样,先排列出目标状态.然后确定初始状态时使得最多的人在目标位置上,然后交换.但是得到的答案总是偏大一点.
然后我又把所有可以使最多的人在原位目标位置上的可能都尝试了一编(包括正反两个目标状态),结果还是只能过8个点,有2个点死都过不了!
我的算法有什么问题吗?
0
回复 luanjiyang发表于2007-11-08 08:44
很委琐的说 我提交了8遍。。
0→0→10→10→10→10→70→AC
-||
0
回复 lonelycorn发表于2007-11-05 23:31
数论……好底歇的东西。
0
回复 gamejifan发表于2007-11-04 11:15
这题的叙述,让我误会了一年多。tzkq……3q..要早知道是这种意思早就ac了这题。。显然没什么大意思,看过组合数学或者学过群论的都懂。。ms跟polya计数法那个循环的意思。。
写的时候竟然因为交换的时候写错一个字母wa。我汗。
0
回复 Alexandria发表于2007-11-01 13:33
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
好强大的题啊,不看题解还真不会!
0
回复 clfhaha1234发表于2007-10-30 18:09
请问什么是置换群啊?可以讲讲吗?………………
0
回复 rleepas发表于2007-10-30 13:18
楼下都是正解?
......
0
回复 Ice_Msk发表于2007-10-18 20:35
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
什么是置换群?不知道。。。照样过。。。。
0
回复 junlonely发表于2007-10-18 20:13
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 江南不才发表于2007-10-11 16:19
排序法这里会超时~
比赛的时间是2S~~
这里是1S~~
(_)
0
回复 秒杀群众发表于2007-10-10 17:05
居然是置换群。。。
对了。。。什么是置换群...
上网查啊!!!
0
回复 southstarj1发表于2007-10-02 18:50
思想:
置换群。(相关知识自己查)
对于一组数据,按各人的意愿排出一个序列,
如果无法排出,就输出-1。
再将环状序列变成链状,则这个目标序列为一个置换群,
与原序列(按1到n的一列)满足:
交换的最少人数等于目标序列与原序列不重合的人数。
因为总共有2n个目标序列(正反各n种),都算一遍就行了。
步骤:
读入数据;
构造一个目标序列;
统计该序列中元素位置与该元素在原序列位置的差值(同一方向)为i{i ∈ [0, n)}的元素个数;
将该序列的反序统计一遍;
从这些数据中选取一个最大的值max;
输出n - max;
注意:
构造目标序列时判断能否构造的条件;
统计一次差值的复杂度是O(n);
统计差值的目的是求与原序列最多的重合人数;
0
回复 wangjin5发表于2007-09-19 22:38
好经典的题奥
确实有难度
0
回复 the_melody发表于2007-09-03 17:58
Accepted 有效得分:100 有效耗时:0ms
好经典的题奥
0
回复 richardxx发表于2007-08-22 17:36
下面程序是错的,不好意思,弄错地方了....
0
回复 sm-star发表于2007-08-21 15:18
题目所求就是每次进行连续交换的人数总和,这样,一个看似复杂的题目就变的异常的简单了!
0
回复 wasyyyy发表于2007-08-11 02:05
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
HOHO~~~看讨论的时候看到有人提到‘置换群’这个东西,突然想起来我刚买的一本组合数学上有这么一块东西,就拿过来看了。。。。
然后就出现上面的东西了。。。。置换群,本来想求轮换的,发现轮换比较多,还是找不参与交换的比较好记。。。。
优化的方法。。。我看了下好象不只一个人讲过了。。。而且似乎我跟他们的都一样(没仔细看)所以就不说了。。。效率是O(n)的。。不用建环。
0
回复 angieqiu发表于2007-08-10 22:49
怎么判断建环失败啊?我的程序虽然AC但总觉得方法很傻
0
回复 梦ぁ逍遥发表于2007-07-17 13:45
想到了用t[i]=b[i]-i表示环
却没想到镜像..
十分感谢visister
让我从90分中挣扎出来...
0
回复 visister发表于2007-06-01 00:12
首先明显地可以知道我们需要对于目标状态建立出一个环。如果无法建立这个环,那么结果一定是-1,当建立好环以后可以知道最小移动代价一定等于最少的不在目标位置上的人数。那么我们可以对目标环进行顺时针旋转1~n-1之中任意一个,答案就一定等于旋转中的不在自己位置上的人数最少的那样的环的状态。但是对于50000的数据,我们如果要将环旋转1~n-1次,那么总共加上判断不在自己位置上的人数时间复杂度为O(n^2),显然在限定时间内是无法出解的。因此我们进行逆向思维:不在自己位置上最少的人数就一定会等于总人数减去在自己位置上最多的人数(仔细想想),那么我们就将该问题转化为了求在自己的位置上最多的人数,这样一来,我们对初始目标环中每一个位置进行判断需要旋转多少次可以回到自己位置上,每一个人的选择都将映射到[0..n-1]的数组中,选取当中最大的情况就为所求,但是考虑到环可以反转,那么我们还需要将环再求一次镜像,就可以得到初始目标需要旋转多少次可以得到在自己位置上最多的人数的环的状态,最后通过总的人数减去它即为问题所求,时间复杂度为O(n);
0
回复 pyh119发表于2006-11-16 20:11
哪个人不小心失火了找我啊!!!
PS:我是安徽省芜湖市119接线员....
0
回复 maomingming发表于2006-11-06 18:40
考虑旋转后最多可能重合的情况,另要注意圈可以反过来
0
回复 qian5发表于2006-09-30 21:35
直接输出‘-1’有一个点过
0
回复 BambooLeaf发表于2006-09-26 18:17
见过的最牛最简单的方法……
将此题转换为冒泡排序,记录下所有交换的次数和两数间的距离,加上就行了……—__—|||
具体是这样的,我们反向思维,本来是要求一个有序数列求出成为无序数列的代价,现在我们把无序数列(即目标数列)进行冒泡排序,然后……就是这样……
看完之后,偶巨汗……
0
回复 xcjzj发表于2006-09-26 17:18
每组数据确定两组相对位置关系,并且这两组互为镜像。
对于某一种排列方式,不在需要位置上的人数即为当前状态到目标状态的最小代价。
先找出其中一种排列方式。由于目标状态可以通过旋转而使得部分人的变化次数减少,所以找出每个人通过某一固定方向旋转到达目标位置的旋转次数。找到某一次数,使得拥有这个次数的人数最多。那么,通过旋转这一最多人拥有的次数,即可使得尽可能多的人不通过交换直接到达目标位置。于是,不拥有这一旋转次数的人数即为这一状态下的最小代价。
然后,用现在的目标状态找出其镜像状态,并且用上述方法再找一遍最小代价,与前面的结果比较,较小值即为答案。
另外,题目中会出现一些无解的情况:
1.某个人被“要”的次数多于两次,也就是说有多于两个的人想要与他(她)邻座,那么无解。
2.根据要求得出的目标状态为多于一个的环,也无解。
0
回复 东邪歪刀发表于2006-07-28 17:27
提交了若干次……残念……
0
回复 sugar发表于2006-07-28 16:26
这题比赛时真有人ac?
真不好想
为什么得开longint啊?
0
回复 晶星发表于2006-07-25 13:29
排列本质不同的只有二种 正着和反着的
检验几个人不在位置上用数学方法:)模拟法超时的
0
回复 tzkq发表于2006-07-23 04:37
注意别误解题意 b1,b2....bm并不指连续位置上的数
0
回复 Coldwings发表于2006-01-26 09:21
可以用群论证明:如果有k个人不在自己的位置上,那么要且仅要k的代价,即可使这些人归位
剩下的..很简单了吧...
0
回复 lemon_cn发表于2008-08-08 15:55
热烈庆祝用pascal AC的第二题~
p.s.我是C++的~~
0
回复 yingjiangyu发表于2015-02-15 21:55
打‘Wrong!’有50分。。
0
回复 东大微雕发表于2015-02-07 15:20
这道题真是太好了。奇妙无穷。
include<iostream> include<string.h> include<stdio.h>
using namespace std;
int a[50005];
int size;
void go(){
int i, j;
int ans = 0;
int dis[50005];
memset(dis, 0, sizeof(dis));
for (i = 1; i <= size; i++){
int d = (a[i] - i + size) % size;
dis[d]++;
}
for (i = 0; i < size; i++){
if (ans < dis[i])
ans = dis[i];
}
memset(dis, 0, sizeof(dis));
for (i = 1; i <= size; i++){
int d = (a[size+1-i]-i+size) % size;
dis[d]++;
}
for (i = 0; i < size; i++){
if (ans < dis[i])ans = dis[i];
}
cout << size-ans << endl;
}
int main(){
freopen("in.txt", "r", stdin);
int neibor[50005][2];
int i;
cin >> size;
for (i = 1; i <= size; i++){
scanf("%d%d",&neibor[i][0],& neibor[i][1]);
}
bool used[50005];
memset(used, 0, sizeof(used));
a[1] = 1;
used[1] = true;
for (i = 2; i <= size; i++){
int last = a[i - 1];
if (!used[neibor[last][0]]){
a[i] = neibor[last][0];
used[a[i]] = true;
}
else if (!used[neibor[last][1]]){
a[i] = neibor[last][1];
used[a[i]] = true;
}
else {
cout << -1 << endl;
return 0;
}
}
if (neibor[1][0] != a[size] && neibor[1][1] != a[size]){
cout << -1 << endl;
return 0;
}
go();
return 0;
}
0
回复 3516发表于2014-07-30 08:59
include<stdio.h>
include<string.h>
int data[50001][2],shi[50001],a[50001];
int main()
{
int n,i,j,qian,hou; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d%d",&data[i][0],&data[i][1]); } a[1]=1;shi[a[1]]=1 for(i=2;i<=n;i++) { qian=data[a[i-1]][0]; hou=data[a[i-1]][1]; if(shi[qian]==0) { a[i]=qian; shi[qian]=1; } else if(shi[hou]==0) { a[i]=hou; shi[hou]=1; } else { printf("-1"); return 0; } } int temp=0,max=0; memset(shi,0,sizeof(shi)); for(i=1;i<=n;i++) { temp=(n+a[i]-i+1)%n; shi[temp]++; } for(i=0;i<n;i++) { if(max<shi[i]) { max=shi[i]; } } memset(shi,0,sizeof(shi)); for(i=1;i<=n;i++) { temp=(n+a[n-i+1]-i+1)%n; shi[temp]++;
}
for(i=0;i<n;i++)
{
if(max<shi[i])max=shi[i];
}
printf("%d",n-max);
}
0
回复 S.Y.F发表于2013-08-31 14:04
题解
1111111129回复于2014-08-13 11:52
orzorzorz
0
回复 S.Y.F发表于2013-07-29 16:55
从10、到30、到100。。。。。。
题解:http://blog.163.com/syf_light_feather/blog/static/223755067201362945326756/
0
回复 vcvycy发表于2013-06-30 00:56
20 30 40 50 70 分都有~泪流满面.
Accepted
100
772 2
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:55:05
Wrong Answer
70
613 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:53:24
Wrong Answer
70
686 2
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:45:35
Wrong Answer
70
856 2
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:42:12
Wrong Answer
70
803 2
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:37:26
Wrong Answer
70
882 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:22:39
Wrong Answer
70
1145 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:20:30
Wrong Answer
10
733 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:11:30
Wrong Answer
50
723 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:04:20
Wrong Answer
50
781 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:55:49
Wrong Answer
40
656 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:49:49
Wrong Answer
40
758 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:44:00
Time Exceeded
30
7160 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:38:22
Time Exceeded
20
7135 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:35:08
0
回复 SEX丶Elope发表于2013-02-16 10:10
点击查看程序源码+详细题解
cuichen回复于2014-09-09 09:24
怎么又是你??你有什么企图?骗访问量???垃圾!
0
回复 qyjubriskxp发表于2010-07-09 21:31
再一次体会到c++流的悲剧,秒杀和3s原来只是输入方式的不同,杯具~~
yuyilahanbao回复于2014-01-24 11:47
从c转到c++第一次不AC(除去忘记把语言有c改为c++的)就是因为c++输入输出的问题
从那次起,我的c++的输入都是用scanf和printf了
因为
保险
安全
我记不清cin是<<还是>>
printf和scanf相对更灵活
....
0
回复 slm发表于2010-03-16 18:27
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
嘿嘿
0
回复 superyoi发表于2009-11-10 11:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
superyoi killed p1008 with a headshot by awp
0
回复 200853349发表于2009-11-10 10:49
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
当我看到众位神牛打出“置换群”三个字后,我在黑书百度GOOGLE维基百科逛了得有一个半小时多然后回来AC了。。。
思路和strini神牛的基本一样。
0
回复 sinb发表于2009-11-09 13:02
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
其实很简单,不要想复杂了,先是想办法构成,然后用置换群的方法即可ac。
0
回复 香蕉派发表于2009-11-06 11:29
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
虽然不懂什么叫置换群,但是思路还是很清晰的。。
0
回复 赏金神侠PPF发表于2009-11-05 11:45
一星星纪念~
0
回复 strini发表于2009-10-30 22:11
根据群论原理,任何置换群都可以分解为若干个循环节。显然,这道题目就是冲着这点来的。因为如果某循环的长度为L,那么本题中只需要代价为L的操作。注意,这里的L!=1,这是因为只有一个人的循环节不需要任何代价的操作。到这里才只能拿三十分,因为圈是可以旋转的,常规方法需要O(n^2)才能解决。不妨这里以编号为1的人为基准,定义每个人到自己应该所在位置的距离。距离不超过n-1。可以通过最大值来寻找能在自己位置上的最多的人数(因为距离为x的人在旋转x次后转到自己的位置上),那么在比较好的情况下,可以优化到O(n)。
TIME: 1H
SUBMIT:
1 70 Error: 发现希望相邻是不精确的,于是改了个搜索方向。(以为题目给定的是按照左右方向,白书说过不能“假定”!)。
2 90 Error: 终于明白要取两个搜索方向的最大值。
3 Accepted.
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 skykey发表于2009-10-29 17:58
include<iostream>
using namespace std;
int n;
int a[50001],b[50001],c[50001];
int aim[50001];
void G_MAP()
{
bool mark[50001]={false};
int p=1,r=1;
while(p<=n)
{
aim[p]=r;mark[r]=true;p++;
if(!mark[a[r]])r=a[r];
else if(!mark[b[r]])r=b[r];
else if(p<=n){cout<<-1;exit(0);}
}
}
int COMPULATE()
{
int max=0;
int t;
int record[2][50001];
for(int i=1;i<=n;i++)record[0][i]=record[1][i]=0;
for(int i=1;i<=n;i++)
{
if((t=aim[i]-i)<0)t+=n; record[0][t]++; if(record[0][t]>max)max=record[0][t];
if((t=aim[i]-(n+1-i))<0)t+=n; record[1][t]++; if (record[1][t]>max)max=record[1][t];
}
return max;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{scanf("%d%d",&a[i],&b[i]);c[a[i]]++;c[b[i]]++;}
for(int i=1;i<=n;i++)if(c[i]!=2){cout<<-1;return 0;}
G_MAP();
int T=COMPULATE();
cout<<n-T;
}
0
回复 song19931218发表于2009-10-27 20:11
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
考虑两种情形(貌似这两种情形很像,但又真的不同,后来才想起,在化学的手性碳原子那部分遇到过类似情况。。。)
然后就是运用置换群的知识
0
回复 Aries_C发表于2009-10-25 08:24
正反两遍...两遍...<幽幽的声音飘远..>
不然就是70分啊...
不看题解的情况下竟然自己想到了...
记得以前老师给我们做过这题的..细节什么的现在做又忘记了..唉..
0
回复 国防安全员001发表于2009-10-21 22:00
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1701人
提交 4835次
通过率 35%
难度 3
题目表述有问题。。
0
回复 liubosen发表于2009-10-21 21:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
yaaaayyayayyayayayayayayayayayayayayayayayyaayayayayayayyaayayayay
var
n,max,i:longint;
a,b,c,d:array[0..50001] of longint;
begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
c[1]:=1;
c[2]:=a[1];
for i:=3 to n do
if c=a[c] then c[i]:=b[c]
else
if c=b[c] then c[i]:=a[c]
else begin
writeln(-1);
halt
end;
if c[n]<>b[1] then
begin
writeln(-1);
halt
end;
fillchar(d,sizeof(d),0);
for i:=1 to n do
inc(d[(c[i]-i+n)mod n]);
for i:=0 to n-1 do
if d[i]>max then max:=d[i];
fillchar(d,sizeof(d),0);
for i:=1 to n do
inc(d[(c[i]+i-1)mod n]);
for i:=0 to n-1 do
if d[i]>max then max:=d[i];
writeln(n-max);
end.
0
回复 lishunzhi发表于2009-10-21 00:11
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
置换群,但建环是重点
0
回复 zebra发表于2009-10-03 09:48
include <iostream> include <cassert>
using namespace std;
long N,seq[50001],p=1;
class
{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2)
{
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2)
return true;
return false;
}
public:
bool AddE(long v1,long v2)
{
if(isnbr(v1,v2))
return true;
else
if(nbr[v1][0]==2||nbr[v2][0]==2)
return false;
else
{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i)
{
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++)
{
if(!flag[nbr[i][j]])
{
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve()
{
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N; b=seq[i]-(N+1-i); if(b<0) b+=N; if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main()
{
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++)
{
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2))
{
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
system("pause");
return 0;
}
0
回复 -117-Join发表于2009-09-18 21:29
哪位大牛帮忙看看我错哪里了
它只得90分
program fire;
type
arr=record
l,r:longint;
end;
var
num:array[1..50000]of longint;
a:array[1..50000]of arr;
b:array[1..50000]of longint;
i,k,j,n:longint;
begin
readln(n);
for i:=1 to n do
readln(a[i].l,a[i].r);
b[1]:=1;
b[n]:=a[1].l;
if a[b[n]].l=b[1]then b[n-1]:=a[b[n]].r
else b[n-1]:=a[b[n]].l;
i:=n-1;
b[2]:=a[1].r;
j:=2;
while j<=i do
begin
if b<>a[b[i]].l then b:=a[b[i]].l
else b:=a[b[i]].r;
dec(i);
if b[j-1]<>a[b[j]].r then b[j+1]:=a[b[j]].r
else b[j+1]:=a[b[j]].l;
inc(j);
end;
for i:=2 to n-1 do
if(b<>a[b[i]].r)and(b<>a[b[i]].l)or(b<>a[b[i]].r)and(b<>a[b[i]].l)then
begin
write(-1);
halt
end;
if(b[n]<>a[b[1]].l)and(b[n]<>a[b[1]].r)or(b[2]<>a[b[1]].l)and(b[2]<>a[b[1]].r)or(b[1]<>a[b[n]].l)and(b[1]<>a[b[n]].r)or(b[n-1]<>a[b[n]].l)and(b[n-1]<>a[b[n]].r)then
begin
write(-1);
halt
end;
num[0]:=0;
for i:=1 to n do
begin
a[b[i]].l:=i;
num[i]:=0;
end;
for i:=1 to n do
if a[i].l-i>=0 then inc(num[a[i].l-i])
else inc(num[a[i].l-i+n]);
j:=0;
for i:=0 to n do
if num[i]>j then j:=num[i];
write(n-j);
end.
写的有点长
0
回复 fs302发表于2009-09-17 20:13
分析:学一个好思想:正难则反!由顺序到乱序我们很难快速找到,但是我们知道如何从乱序变为顺序!解决本题利用了组合数学中置换群的思想。
从第一个人处断开,将圆环的问题转化为序列的问题。如果可以,求出目标序列。求出目标序列复杂度O(n).
求出目标序列右移0至n-1位置时,不需要移动的人数。将目标序列反转,再求出目标序列右移0至n-1位置时,不需要移动的人数。求不需要移动的人数最大等价于求需要移动的人数最小。复杂度O(n)。
更详细的说:
引进“相对有序”这个概念,当两个人满足C[j]-C[i]==j-i时,两个相对有序。
题目要求最小的总代价,但是我们可以考虑倒过来想,要求最小的总代价亦即求最多有多少人不用移动,亦即相对有序。
然后我们引进一个辅助变量T=C-I,{C-I>=0},T=C[i]-I+N,{C[i]-I<0},那么这个T[i]有什么意义呢?我们知道初始状态的编号是1-N,而目标状态是C[1]-C[N],那么C-I便是从目标状态到初始状态顺时针所要移动的距离,那么如果那么T值相等的两个同学则是相对有序的,亦即不用移动,我们只要找出最大的T然后N-Max(T)就是得到的结果,但是这样还不够,因为刚刚那样只是顺时针所要移动的距离,我们还要计算逆时针的到的结果,从顺时针和逆时针中找到最大的T,然后N-Max(T)才能够是正确结果.
0
回复 maxint64发表于2009-09-01 21:33
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
先是物理大发了——以为 b1,b2...bm是连续的
看了牛们的题解 一次ac :)
0
回复 柔情使者发表于2009-08-20 15:44
第一遍做的时候没有看题解,自己测了好几遍总是60分,看了n多大牛的解释才恍然大悟,竟然要正反两遍!!!唉,幸亏咱有测试数据,否则我可就惨了...
O(n)的求目标队列算法,都说是冒泡排序,我没看出来,倒是有点像。
0
回复 maxiem发表于2009-08-18 20:55
物理自重啊,嘿嘿。
注意要正反两遍哦~
9MS?
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 9ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:9ms
(好像那个冒泡是口胡,大家不要被那个蒙了
program fire;
var
st:array [1..50000,1..2] of longint;
k,final:array [0..50000] of longint;
ex:array [1..50000] of boolean;
p,max,i,n:longint;
begin
fillchar (st,sizeof(st),0);
fillchar (ex,sizeof(ex),0);
fillchar (final,sizeof(final),0);
fillchar (k,sizeof(k),0);
readln (n);
for i:=1 to n do readln (st,st);
final[1]:=1;p:=2;ex[1]:=true;
for i:=1 to n do begin
if ex[st[final[i],1]]=false then begin
final[p]:=st[final[i],1];
ex[st[final[i],1]]:=true;
inc(p);
end
else if ex[st[final[i],2]]=false then begin
final[p]:=st[final[i],2];
ex[st[final[i],2]]:=true;
inc(p);
end;
end;
if p-1<>n then begin
writeln (-1);
halt;
end;
max:=0;
for i:=1 to n do if final[i]>=i then inc(k[final[i]-i]) else inc(k[n-i+final[i]]);
for i:=0 to n-1 do if k[i]>max then max:=k[i];
fillchar (k,sizeof(k),0);
for i:=n downto 1 do if final[i]>=n-i+1 then inc(k[final[i]-n+i-1]) else inc(k[final[i]+i-1]);
for i:=0 to n -1 do if k[i]>max then max:=k[i];
writeln (n-max);
end.
0
回复 suning发表于2009-08-14 09:43
啊呜~
一年前误解了题意~
一年后理解了题意~
然后就是1次美妙的AC
PS:[误]解[理]解~~~[物理]?
0
回复 fengwuliu发表于2009-08-13 17:20
lgxcgd说的太对了!太感谢了5555
0
回复 Matt发表于2009-08-11 22:28
NOIP也会考高等数学...
由于原图是环,所以置换群可表示为一次循环。作差是个好方法。
但求冒泡排序是怎么作的
0
回复 3830372发表于2009-08-11 21:28
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1504人
提交 4282次
通过率 35%
难度 3
提交 讨论 题解 状态
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 尖端才子发表于2009-08-11 11:14
纪念一下……第1500个AC……
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1500人
提交 4274次
通过率 35%
难度 3
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 SecretAgent发表于2009-08-10 14:02
置换群是正解
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 yangbei发表于2009-08-07 14:57
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 338ms
├ 测试数据 05:答案正确... 322ms
├ 测试数据 06:答案正确... 306ms
├ 测试数据 07:答案正确... 338ms
├ 测试数据 08:答案正确... 338ms
├ 测试数据 09:答案正确... 322ms
├ 测试数据 10:答案正确... 306ms
Accepted 有效得分:100 有效耗时:2270ms
算镜像时偷了点懒,不过也算一遍AC了
0
回复 ja_son发表于2009-08-06 15:44
a:拆环成队,寻求目标队列。
b:b1,b2...bm不是连续的,而且是任意的。只要有成立目标队列,与原来的队列相匹配就可以知道有多少(设为n个)需要移动位置,则代价就是n。
c:目标队列有多种情况,可以反转,也可以左右移动。
0
回复 1s发表于2009-08-03 17:56
如对本题有疑问可以参看我的题解:
http://xujieqi.blog.hexun.com/35722312_d.html
0
回复 DMKaplony发表于2009-07-30 15:15
当时的时间限制好像是2s。。有个题解说把1定为第一项然后进行冒泡排序。。不过这里是1s 啊。。。也行只有置换群了吧。
0
回复 xusc_2009发表于2009-07-28 14:30
看不懂,只好搁浅
什么时候想清楚了再做
0
回复 董发表于2009-07-24 19:11
program p1008;
var i,n,k,j,sum1,sum2,ans,max:longint;
a,b,w,d,c:array[0..50005] of longint;
begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
w[1]:=1; w[2]:=a[w[1]];
k:=1;
repeat
inc(k);
if w[k-1]=a[w[k]] then w[k+1]:=b[w[k]]
else if w[k-1]=b[w[k]] then w[k+1]:=a[w[k]]
else begin
writeln(-1);
exit;
end;
until k=n;
if w[n+1]<>w[1] then
begin
writeln(-1);
exit;
end;
for i:=1 to n do
begin
a[i]:=w[i]-i;
b[i]:=w[n-i+1]-i;
if a[i]<0 then a[i]:=a[i]+n;
if b[i]<0 then b[i]:=b[i]+n;
inc(c[a[i]]);
inc(d[b[i]]);
end;
for i:=0 to n-1 do
begin
if ans<c[i] then ans:=c[i];
if ans<d[i] then ans:=d[i];
end;
writeln(n-ans);
end.
0
回复 我飞发表于2009-07-23 21:00
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 93狒狒发表于2009-07-23 20:59
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
秒杀......
0
回复 fjxmlhx发表于2009-07-22 13:15
置换群,做2n次,顺时针和逆时针.
对于一个置换,最小操作费用是所有循环长度的和.因此实际上是找出2n个置换中哪个置换循环长度为1的数量最多.
0
回复 340508965发表于2009-07-21 15:01
⊙﹏⊙b汗
不知道的以为这是数学竞赛......
...
我的数论与图论可以说脑袋里空白一片.........
怎么办,我的竞赛啊
........
算了 看了题解 大家写的
总算弄懂这道题了
先前以为b1,b2,b3..bm是连续的
没想到是任意的!!!!!!!!!
诶 叹悲歌未切 为撼奈何编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
总算AC了
program p1008;
var i,n,k,j,sum1,sum2,ans,max:longint;
a,b,w,d,c:array[0..50005] of longint;
begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
w[1]:=1; w[2]:=a[w[1]];
k:=1;
repeat
inc(k);
if w[k-1]=a[w[k]] then w[k+1]:=b[w[k]]
else if w[k-1]=b[w[k]] then w[k+1]:=a[w[k]]
else begin
writeln(-1);
exit;
end;
until k=n;
if w[n+1]<>w[1] then
begin
writeln(-1);
exit;
end;
for i:=1 to n do
begin
a[i]:=w[i]-i;
b[i]:=w[n-i+1]-i;
if a[i]<0 then a[i]:=a[i]+n;
if b[i]<0 then b[i]:=b[i]+n;
inc(c[a[i]]);
inc(d[b[i]]);
end;
for i:=0 to n-1 do
begin
if ans<c[i] then ans:=c[i];
if ans<d[i] then ans:=d[i];
end;
writeln(n-ans);
end.
0
回复 zsy90943发表于2009-07-18 00:51
构造巧妙、、看来还是要学好数论和图论额、、、、
0
回复 POM无敌牛B发表于2009-07-16 11:47
编译通过...
├ 测试数据 01:运行超时...
├ 测试数据 02:运行超时...
├ 测试数据 03:运行超时...
├ 测试数据 04:运行超时...
├ 测试数据 05:运行超时...
├ 测试数据 06:运行超时...
├ 测试数据 07:运行超时...
├ 测试数据 08:运行超时...
├ 测试数据 09:运行超时...
├ 测试数据 10:运行超时...
Unaccepted 有效得分:0 有效耗时:0ms
无奈 哪位哥哥救救我
0
回复 yxy发表于2009-06-16 18:16
把置换解释成度为2图,真有才.
求出序列,正反分别做一次差就行了.
0
回复 sxpeter发表于2009-06-14 16:56
讲建环吧。数组w表示环,我用的是一种类似并查集的方法。
begin
read(n);
for i:=1 to n do read(a[i],b[i]);
t:=2;w[1]:=1;w[2]:=a[1];
while true do begin
if a[w[t]]<>w[t-1]then w[t+1]:=a[w[t]]//是否在左边
else if b[w[t]]<>w[t-1]then w[t+1]:=b[w[t]]//是否在右边
else begin writeln(-1);halt;end;//失败判断
inc(t);
if t>n then break;
end;
if w[n+1]<>w[1]then begin writeln(-1);halt;end;//本句一定要加!!!!!!
end.
0
回复 lgxcgd发表于2009-05-17 20:24
首先把这个圈看做一个图,每个同学看做一个顶点。因为要形成环,所以每个顶点的度必须为2。
如果存在度数不为2的顶点,那么整个图无法构成一个环,即“无论怎么调整都不能符合每个同学的愿望”输出-1。
如果是一个环,那么就遍历图,生成以第1个顶点为开头的序列。现在就要求出最小移动的代价。
在理解题意所述的调整方式中,要注意实际上就是把M个在错误位置上的人移动到正确的位置上,代价为M。一次下令移动即可。
假如生成的目标序列为1,5,3,2,4。我们现在就需要比较它和初始状态1,2,3,4,5,看有几个人离开了原来的位置。但这个序列实际代表的是一个环,而且方向正反有两种,就需要把初始序列正反分别转N次,和得到的序列比较,看其中最少有几个位置上的人编号不相同,就得到了我们要求的最小代价。
上述方法有大量冗余。但可以发现转来转去不管怎么转,任意两个人之间的相对位置关系在这过程中都不会变。于是想到做差,如果差小于0则加上N。
1 5 3 2 4
- 1 2 3 4 5
0 3 0 3 4
这表示序列1,5,3,2,4不转动时1,3两个人在原来的位置上,转动3个位置后5和2两个人在原来的位置上,转动4个位置后只有4一个人会在原来的位置上。这就是说,1,5,3,2,4与1,2,3,4,5在旋转后最多有2个位置上的人编号相同,即最少有3个位置上的人编号不相同。同理要反转再求一次。
记录每个不同的差值的个数,取其最大值P,即不调换次数最大的。结果N-P就是调换次数最小的。
0
回复 src250发表于2009-05-14 08:27
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
切记:重新构图时一定要对数组清空!我的第一次只有50分,就是这个原因!
0
回复 love19960108发表于2009-04-26 17:59
这题可以用C++这样做么??
include <iostream> include <cassert>
using namespace std;
long N,seq[50001],p=1;
class{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2){
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2) return true;
return false;
}
public:
bool AddE(long v1,long v2){
if(isnbr(v1,v2)) return true;
else if(nbr[v1][0]==2||nbr[v2][0]==2) return false;
else{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i){
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++){
if(!flag[nbr[i][j]]){
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve(){
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N; b=seq[i]-(N+1-i); if(b<0) b+=N; if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main(){
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++){
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2)){
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
return 0;
}
0
回复 voyagec2发表于2009-03-18 15:53
难理解,不过算法很精妙
0
回复 pRoevollove发表于2009-02-25 23:49
天,把(p[i]-i+n)mod n理所当然地打成了abs(p[i]-i)
结果一直50分……还一直以为自己构造错了……
ps 我可以过楼下的范例哦
0
回复 ufo172849z发表于2009-01-24 23:05
ms楼下的程序不能处理这种反例(测试数据还是不够强啊)
6
2 3
1 3
1 2
5 6
4 6
4 5
应该输出-1的吧?因为是两个环
var a,b:array[0..50000]of longint;
c:array[0..50000,1..2]of longint;
d:array[0..50000]of boolean;
i,j,k,m,n,max:longint;
can:boolean;
begin
readln(n);
for i:=1 to n do
readln(c,c);
b[0]:=c[1,1]; b[n]:=c[1,1];
fillchar(d,sizeof(d),0);
k:=1;
can:=true;
for i:=1 to n-1 do
begin
if d[k] then can:=false;
b[i]:=k; d[k]:=true;
if b=c[k,1] then k:=c[k,2]
else if b=c[k,2] then k:=c[k,1]
else can:=false;
if not can then break;
end;
if can then
if b[n]<>k then can:=false;
if can then
begin
max:=-1;
fillchar(a,sizeof(a),0);
for i:=1 to n do
inc(a[(b[i]-i+n) mod n]);
for i:=0 to n-1 do
if a[i]>max then max:=a[i];
fillchar(a,sizeof(a),0);
for i:=1 to n do
inc(a[(b[n-i+1]-i+n)mod n]);
for i:=1 to n-1 do
if a[i]>max then max:=a[i];
writeln(n-max);
end
else
writeln(-1);
end.
0
回复 tangdongjian发表于2009-01-23 22:17
我在做镜像时把原先max直接覆盖上了,注意
0
回复 永恒888发表于2009-10-26 22:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 tangkunjie发表于2009-06-04 19:50
挺烦人的题目
0
回复 ykspeter发表于2008-11-13 20:32
program fire(input,output);
var
n,i,j,k,max,v:longint;
a:array[0..100000,1..2] of longint;
b,c:array[0..100000] of longint;
begin
readln(n);
for i:=1 to n do readln(a,a);
for i:=1 to n do
begin
k:=0;
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if (k=4) or (k=3)
then begin
writeln('-1');
exit
end
end;
b[1]:=1;i:=2;k:=a[1,1];j:=1;
repeat
b[i]:=k;
inc(i);
v:=k;
if a[k,1]<>j
then k:=a[k,1]
else k:=a[k,2];
j:=v;
until i=n+1;
fillchar(c,sizeof(c),0);
for i:=1 to n do inc(c[(b[i]-i+n)mod n]);
for i:=0 to n-1 do
if c[i]>max
then max:=c[i];
fillchar(c,sizeof(c),0);max:=0;
for i:=1 to n do inc(c[(b[n-i+1]-i+n)mod n]);
for i:=n-1 downto 0 do
if c[i]>max
then max:=c[i];
writeln(n-max);
end.
0
回复 getuojian发表于2008-11-10 13:38
include<stdio.h> include<memory.h>
const int maxn=50010;
int n;
int f[maxn][2];
int goal[maxn];
int ans=maxn;
int hash[maxn];
bool SET_ORI(){
bool flag[maxn];
memset(flag, true, sizeof(flag));
goal[1]=1; flag[1]=false;
for (int i=1; i<=n-1; i++){
if (flag[f[goal[i]][0]]){
goal=f[goal[i]][0];
flag[f[goal[i]][0]]=false;
continue;
}
if (flag[f[goal[i]][1]]){
goal=f[goal[i]][1];
flag[f[goal[i]][1]]=false;
continue;
}
return false;
}
if ((goal[n]!=f[1][0]) && (goal[n]!=f[1][1]))
return false;
return true;
}
int SWAP(int i, int j){
int t=goal[i];
goal[i]=goal[j];
goal[j]=t;
return 0;
}
int min(int i, int j){
return i>j?j:i;
}
int HASH(){
for(int i=1; i<=n; i++)
hash[i]=goal[i]-i+n;
return 0;
}
int CALC(){
int temp[maxn2], back=0;
memset(temp, 0, sizeof(temp));
for (int i=1; i<=n; i++)
temp[hash[i]%n]++;
for (int i=1; i<=2n-1; i++)
if (temp[i] > back)
back=temp[i];
return back;
}
int main(){
freopen("fire.in", "r", stdin);
freopen("fire.out", "w", stdout);
scanf("%d", &n);
for (int i=1; i<=n; i++)
scanf("%d %d", &f[i][0], &f[i][1]);
if (!SET_ORI()){
printf("-1");
return 0;
}
//forward
HASH();
ans=min(ans, n-CALC());
//backward
for (int i=1; i<=n/2; i++)
SWAP(i,n-i+1);
HASH();
ans=min(ans, n-CALC());
printf("%d", ans);
return 0;
}
0
回复 IVORY发表于2008-11-06 10:46
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
CHEAT的...
0
回复 storey p发表于2008-11-05 14:19
回447389831:
exit换成halt
0
回复 FenXy发表于2008-11-04 08:28
艺术p245
0
回复 hlq发表于2008-11-01 14:31
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
求不在位置上的人数
a【i】 第i位上的同学编号
for i:=1 to n do
begin
inc(b[(a[i]-i+n) mod n])
end;
max:=0;
for i:=0 to n-1 do
if b[i]>max then max:=b[i];
fillchar(b,sizeof(b),0);
for i:=1 to n do
begin
inc(b[(a[i]-(n-i+1)+n)mod n]);//对称
end;
for i:=0 to n-1 do
if b[i]>max then max:=b[i];
0
回复 Will~骷髅发表于2008-10-30 21:37
编译通过...
├ 测试数据 01:运行超时...
├ 测试数据 02:运行超时...
├ 测试数据 03:运行时错误...|错误号: -1073741819
├ 测试数据 04:运行时错误...|错误号: -1073741819
├ 测试数据 05:运行时错误...|错误号: -1073741819
├ 测试数据 06:运行时错误...|错误号: -1073741819
├ 测试数据 07:运行时错误...|错误号: -1073741819
├ 测试数据 08:运行时错误...|错误号: -1073741819
├ 测试数据 09:运行时错误...|错误号: -1073741819
├ 测试数据 10:运行时错误...|错误号: -1073741819
Unaccepted 有效得分:0 有效耗时:0ms
怎么会这样???
0
回复 悲伤逆流成河发表于2008-10-28 22:13
include <iostream> include <fstream>
using namespace std ;
int hash[50001];
int n , i , j , t , maxs(0) ;
inline void HASH ( int e[] )
{
for ( i = 1 ; i <= n ; i++ )
{
e[i] -= i ;
if ( e[i] < 0 ) e[i] += n ;
hash[e[i]]++ ;
}
for ( i = 0 ; i < 50001 ; i++ )
if ( maxs < hash[i] ) maxs = hash[i] ;
}
int main(){
ifstream fin ("fire.in") ;
ofstream fout ("fire.out") ;
fin >> n ;
int e[n+1] , h[n+1][2] , e2[n+1];
bool f[n+1] ;
for ( i = 1 ; i <= n ; i++ )
{
f[i] = false ;
fin >> h[i][0] >> h[i][1] ;
}
e[1] = 1 ;
f[1] = true ;
for ( i = 2 ; i <= n ; i++ )
{
if ( e < 0 ) { fout << -1 << endl ; exit(0) ; }
if ( !f [ h[ e ][0] ] ) e[i] = h[ e ][0] ;
if ( !f [ h[ e ][1] ] ) e[i] = h[ e ][1] ;
f[ e[i] ] = true ;
}
for ( i = 1 , j = n ; i <= n ; i++,j-- ) e2[j] = e[i] ;
HASH ( e ) ;
memset ( hash , 0 , sizeof ( hash ) ) ;
HASH ( e2 ) ;
fout << n - maxs << endl ;
}
0
回复 evelynhe发表于2008-10-26 16:31
“置换群思想...今天刚明白...
先构造新数列(要构造两次,否则只有70分),然后向右计算相对位置差,然后累加记录数组,然后用N减去相对位置差累加值最大的,就是答案... ”
这是真的
0
回复 true1023发表于2008-10-25 09:32
置换群的基本概念
利用原序列和目标序列每个元素的绝对位置差来求出原序列每个元素对于目标序列的相对位置,找相对位置相同的最多的元素数,用总元素数减去它即为结果。
0
回复 447389831发表于2008-10-21 09:45
program fire(input,output);
var
n,i,j,k,max,v:longint;
a:array[0..100000,1..2] of longint;
b,c:array[0..100000] of longint;
begin
readln(n);
for i:=1 to n do readln(a,a);
for i:=1 to n do
begin
k:=0;
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if (k=4) or (k=3)
then begin
writeln('-1');
exit
end
end;
b[1]:=1;i:=2;k:=a[1,1];j:=1;
repeat
b[i]:=k;
inc(i);
v:=k;
if a[k,1]<>j
then k:=a[k,1]
else k:=a[k,2];
j:=v;
until i=n+1;
fillchar(c,sizeof(c),0);
for i:=1 to n do inc(c[(b[i]-i+n)mod n]);
for i:=0 to n-1 do
if c[i]>max
then max:=c[i];
fillchar(c,sizeof(c),0);max:=0;
for i:=1 to n do inc(c[(b[n-i+1]-i+n)mod n]);
for i:=n-1 downto 0 do
if c[i]>max
then max:=c[i];
writeln(n-max);
end.
90 分,牛人门帮看下把
0
回复 cnfnje1发表于2008-10-17 18:12
置换群.....是什么?
readln(n);
for i:=1 to n do readln(a[i],b[i]);
c[1]:=1; c[2]:=a[1];
for i:=3 to n do if c=a[c] then c[i]:=b[c]
else if c=b[c] then c[i]:=a[c]
else begin writeln(-1); halt end;
if c[n]<>b[1] then begin writeln(-1); halt end;
fillchar(d,sizeof(d),0);
for i:=1 to n do inc(d[(c[i]-i+n)mod n]);
for i:=0 to n-1 do if d[i]>m then m:=d[i];
fillchar(d,sizeof(d),0);
for i:=1 to n do inc(d[(c[i]+i-1)mod n]);
for i:=0 to n-1 do if d[i]>m then m:=d[i];
writeln(n-m);
是么?
0
回复 lyrics发表于2008-10-12 19:55
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
技巧性比较强吧,楼下不必构造2次,计算时从头至尾算一次,再倒过来算一次就行了
0
回复 LV.唱响发表于2008-10-05 08:38
置换群思想...今天刚明白...
先构造新数列(要构造两次,否则只有70分),然后向右计算相对位置差,然后累加记录数组,然后用N减去相对位置差累加值最大的,就是答案...
0
回复 宇智波带波斯猫发表于2008-10-05 08:33
Flag Accepted
题号 P1008
类型(?) 其它
通过 1065人
提交 3000次
通过率 35%
难度 3
第3000个提交的
0
回复 鸳鸯羡发表于2008-09-28 18:19
include <iostream>
using namespace std ;
int hash[50001];
int n , i , j , t , maxs(0) ;
inline void HASH ( int e[] )
{
for ( i = 1 ; i <= n ; i++ )
{
e[i] -= i ;
if ( e[i] < 0 ) e[i] += n ;
hash[e[i]]++ ;
}
for ( i = 0 ; i < 50001 ; i++ )
if ( maxs < hash[i] ) maxs = hash[i] ;
}
int main(){
cin >> n ;
int e[n+1] , h[n+1][2] , e2[n+1];
bool f[n+1] ;
for ( i = 1 ; i <= n ; i++ )
{
f[i] = false ;
cin >> h[i][0] >> h[i][1] ;
}
e[1] = 1 ;
f[1] = true ;
for ( i = 2 ; i <= n ; i++ )
{
if ( e < 0 ) { cout << -1 << endl ; exit(0) ; }
if ( !f [ h[ e ][0] ] ) e[i] = h[ e ][0] ;
if ( !f [ h[ e ][1] ] ) e[i] = h[ e ][1] ;
f[ e[i] ] = true ;
}
for ( i = 1 , j = n ; i <= n ; i++,j-- ) e2[j] = e[i] ;
HASH ( e ) ;
memset ( hash , 0 , sizeof ( hash ) ) ;
HASH ( e2 ) ;
cout << n - maxs << endl ;
}
80分
0
回复 月光疾风发表于2008-09-25 13:03
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
纪念我第200次提交!过第79题。。。。
0
回复 ghostplant发表于2008-09-20 19:48
include <iostream> include <fstream> include <cassert>
using namespace std;
long N,seq[50001],p=1;
class{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2){
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2) return true;
return false;
}
public:
bool AddE(long v1,long v2){
if(isnbr(v1,v2)) return true;
else if(nbr[v1][0]==2||nbr[v2][0]==2) return false;
else{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i){
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++){
if(!flag[nbr[i][j]]){
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve(void){
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N; b=seq[i]-(N+1-i); if(b<0) b+=N; if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main(){
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++){
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2)){
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
return 0;
}
0
回复 zzh19950802发表于2008-09-17 19:29
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案错误... ├ 标准行输出
├ 错误行输出
├ 测试数据 05:答案错误... ├ 标准行输出
├ 错误行输出
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 462ms
├ 测试数据 08:答案正确... 369ms
├ 测试数据 09:答案正确... 384ms
├ 测试数据 10:答案错误...程序输出比正确答案长
为什么我的程序不对?
include <iostream>
using namespace std;
define MAXN 50000
int man[MAXN+2][2];
int cercle[MAXN+2]={0,1};
int used[MAXN+2]={0};
int reduce[2][MAXN+2]={0};
int n;
int main()
{
long i,p,q=1,t;
int max=0;
cin>>n;
for (i=1;i<=n;i++) cin>>man[i][0]>>man[i][1];
p=man[q][1];
for (i=2;i<=n+1;i++)
{
if (man[q][1]==p)
{
p=q;
q=man[q][0];
}
else
{
if(man[q][0]!=p) break;
p=q;
q=man[q][1];
}
if(used[q]) break;
else used[q]=1;
cercle[i]=q;
}
if (i<=n+1) cout<<-1;
else
{
for (i=1;i<=n;i++)
{
if((t=cercle[i]-i)<0) t+=n; reduce[0][t]++; if (reduce[0][t]>max) max=reduce[0][t];
if ((t=cercle[i]-n+i-1)<0) t+=n; if (reduce[1][t]>max) max=reduce[1][t];
}
cout<<n-max;
}
return 0;
}
0
回复 liaorc发表于2008-09-16 17:56
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 cxy450090074发表于2008-09-04 13:34
oh no
0
回复 Lost.G发表于2008-08-22 15:49
我在想``怎么样才能不看错这题呢
0
回复 bonism发表于2008-08-14 21:30
时间复杂度O(N)。。。
原来我一直把题意理解错。。。囧!!。。
关于“置换群”,请看LRJ的《算法艺术与信息学竞赛》P245那一小节,还是比较好理解的。
0
回复 lemon_cn发表于2008-08-08 15:55
热烈庆祝用pascal AC的第二题~
p.s.我是C++的~~
0
回复 oipn4e2发表于2008-08-05 21:36
解决效率不高,但AC了。
0
回复 notblack发表于2008-08-01 09:17
用距离来分类,统计在原位的最大人数,奇怪的是
b[1]:=1;
b[2]:=a[1,1];
b[n]:=a[1,2];
建环的时候,上面的改成
b[1]:=1;
b[2]:=a[1,2];
b[n]:=a[1,1];
最后一个点却过不了,太奇怪了.
0
回复 332404521发表于2008-07-14 13:53
对于初三刚刚中考完的我,要理解这题的意思是万万不能的。。。
看题解我知道了应该怎么做,但那不是我的,所以不做了。。。
哪天能证明出来那啥再来做
0
回复 Sheeta发表于2007-11-14 15:45
好简单啊
直接贪啊
(P.S.置换群?什么东东...)
0
回复 mingyueyucai发表于2007-11-09 21:22
我代码写了老长老长,结果还是只过了8个点,有没有搞错?
我想请问一下,我和大家的一样,先排列出目标状态.然后确定初始状态时使得最多的人在目标位置上,然后交换.但是得到的答案总是偏大一点.
然后我又把所有可以使最多的人在原位目标位置上的可能都尝试了一编(包括正反两个目标状态),结果还是只能过8个点,有2个点死都过不了!
我的算法有什么问题吗?
0
回复 luanjiyang发表于2007-11-08 08:44
很委琐的说 我提交了8遍。。
0→0→10→10→10→10→70→AC
-||
0
回复 lonelycorn发表于2007-11-05 23:31
数论……好底歇的东西。
0
回复 gamejifan发表于2007-11-04 11:15
这题的叙述,让我误会了一年多。tzkq……3q..要早知道是这种意思早就ac了这题。。显然没什么大意思,看过组合数学或者学过群论的都懂。。ms跟polya计数法那个循环的意思。。
写的时候竟然因为交换的时候写错一个字母wa。我汗。
0
回复 Alexandria发表于2007-11-01 13:33
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
好强大的题啊,不看题解还真不会!
0
回复 clfhaha1234发表于2007-10-30 18:09
请问什么是置换群啊?可以讲讲吗?………………
0
回复 rleepas发表于2007-10-30 13:18
楼下都是正解?
......
0
回复 Ice_Msk发表于2007-10-18 20:35
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
什么是置换群?不知道。。。照样过。。。。
0
回复 junlonely发表于2007-10-18 20:13
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 江南不才发表于2007-10-11 16:19
排序法这里会超时~
比赛的时间是2S~~
这里是1S~~
(_)
0
回复 秒杀群众发表于2007-10-10 17:05
居然是置换群。。。
对了。。。什么是置换群...
上网查啊!!!
0
回复 southstarj1发表于2007-10-02 18:50
思想:
置换群。(相关知识自己查)
对于一组数据,按各人的意愿排出一个序列,
如果无法排出,就输出-1。
再将环状序列变成链状,则这个目标序列为一个置换群,
与原序列(按1到n的一列)满足:
交换的最少人数等于目标序列与原序列不重合的人数。
因为总共有2n个目标序列(正反各n种),都算一遍就行了。
步骤:
读入数据;
构造一个目标序列;
统计该序列中元素位置与该元素在原序列位置的差值(同一方向)为i{i ∈ [0, n)}的元素个数;
将该序列的反序统计一遍;
从这些数据中选取一个最大的值max;
输出n - max;
注意:
构造目标序列时判断能否构造的条件;
统计一次差值的复杂度是O(n);
统计差值的目的是求与原序列最多的重合人数;
0
回复 wangjin5发表于2007-09-19 22:38
好经典的题奥
确实有难度
0
回复 the_melody发表于2007-09-03 17:58
Accepted 有效得分:100 有效耗时:0ms
好经典的题奥
0
回复 richardxx发表于2007-08-22 17:36
下面程序是错的,不好意思,弄错地方了....
0
回复 sm-star发表于2007-08-21 15:18
题目所求就是每次进行连续交换的人数总和,这样,一个看似复杂的题目就变的异常的简单了!
0
回复 wasyyyy发表于2007-08-11 02:05
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
HOHO~~~看讨论的时候看到有人提到‘置换群’这个东西,突然想起来我刚买的一本组合数学上有这么一块东西,就拿过来看了。。。。
然后就出现上面的东西了。。。。置换群,本来想求轮换的,发现轮换比较多,还是找不参与交换的比较好记。。。。
优化的方法。。。我看了下好象不只一个人讲过了。。。而且似乎我跟他们的都一样(没仔细看)所以就不说了。。。效率是O(n)的。。不用建环。
0
回复 angieqiu发表于2007-08-10 22:49
怎么判断建环失败啊?我的程序虽然AC但总觉得方法很傻
0
回复 梦ぁ逍遥发表于2007-07-17 13:45
想到了用t[i]=b[i]-i表示环
却没想到镜像..
十分感谢visister
让我从90分中挣扎出来...
0
回复 visister发表于2007-06-01 00:12
首先明显地可以知道我们需要对于目标状态建立出一个环。如果无法建立这个环,那么结果一定是-1,当建立好环以后可以知道最小移动代价一定等于最少的不在目标位置上的人数。那么我们可以对目标环进行顺时针旋转1~n-1之中任意一个,答案就一定等于旋转中的不在自己位置上的人数最少的那样的环的状态。但是对于50000的数据,我们如果要将环旋转1~n-1次,那么总共加上判断不在自己位置上的人数时间复杂度为O(n^2),显然在限定时间内是无法出解的。因此我们进行逆向思维:不在自己位置上最少的人数就一定会等于总人数减去在自己位置上最多的人数(仔细想想),那么我们就将该问题转化为了求在自己的位置上最多的人数,这样一来,我们对初始目标环中每一个位置进行判断需要旋转多少次可以回到自己位置上,每一个人的选择都将映射到[0..n-1]的数组中,选取当中最大的情况就为所求,但是考虑到环可以反转,那么我们还需要将环再求一次镜像,就可以得到初始目标需要旋转多少次可以得到在自己位置上最多的人数的环的状态,最后通过总的人数减去它即为问题所求,时间复杂度为O(n);
0
回复 pyh119发表于2006-11-16 20:11
哪个人不小心失火了找我啊!!!
PS:我是安徽省芜湖市119接线员....
0
回复 maomingming发表于2006-11-06 18:40
考虑旋转后最多可能重合的情况,另要注意圈可以反过来
0
回复 qian5发表于2006-09-30 21:35
直接输出‘-1’有一个点过
0
回复 BambooLeaf发表于2006-09-26 18:17
见过的最牛最简单的方法……
将此题转换为冒泡排序,记录下所有交换的次数和两数间的距离,加上就行了……—__—|||
具体是这样的,我们反向思维,本来是要求一个有序数列求出成为无序数列的代价,现在我们把无序数列(即目标数列)进行冒泡排序,然后……就是这样……
看完之后,偶巨汗……
0
回复 xcjzj发表于2006-09-26 17:18
每组数据确定两组相对位置关系,并且这两组互为镜像。
对于某一种排列方式,不在需要位置上的人数即为当前状态到目标状态的最小代价。
先找出其中一种排列方式。由于目标状态可以通过旋转而使得部分人的变化次数减少,所以找出每个人通过某一固定方向旋转到达目标位置的旋转次数。找到某一次数,使得拥有这个次数的人数最多。那么,通过旋转这一最多人拥有的次数,即可使得尽可能多的人不通过交换直接到达目标位置。于是,不拥有这一旋转次数的人数即为这一状态下的最小代价。
然后,用现在的目标状态找出其镜像状态,并且用上述方法再找一遍最小代价,与前面的结果比较,较小值即为答案。
另外,题目中会出现一些无解的情况:
1.某个人被“要”的次数多于两次,也就是说有多于两个的人想要与他(她)邻座,那么无解。
2.根据要求得出的目标状态为多于一个的环,也无解。
0
回复 东邪歪刀发表于2006-07-28 17:27
提交了若干次……残念……
0
回复 sugar发表于2006-07-28 16:26
这题比赛时真有人ac?
真不好想
为什么得开longint啊?
0
回复 晶星发表于2006-07-25 13:29
排列本质不同的只有二种 正着和反着的
检验几个人不在位置上用数学方法:)模拟法超时的
0
回复 tzkq发表于2006-07-23 04:37
注意别误解题意 b1,b2....bm并不指连续位置上的数
0
回复 Coldwings发表于2006-01-26 09:21
可以用群论证明:如果有k个人不在自己的位置上,那么要且仅要k的代价,即可使这些人归位
剩下的..很简单了吧...
0
回复 lemon_cn发表于2008-08-08 15:55
热烈庆祝用pascal AC的第二题~
p.s.我是C++的~~0
回复 whxc049发表于2015-07-05 11:02
0
回复 yingjiangyu发表于2015-02-15 21:55
打‘Wrong!’有50分。。
0
回复 东大微雕发表于2015-02-07 15:20
这道题真是太好了。奇妙无穷。
include<iostream> include<string.h> include<stdio.h>
using namespace std;
int a[50005];
int size;
void go(){
int i, j;
int ans = 0;
int dis[50005];
memset(dis, 0, sizeof(dis));
for (i = 1; i <= size; i++){
int d = (a[i] - i + size) % size;
dis[d]++;
}
for (i = 0; i < size; i++){
if (ans < dis[i])
ans = dis[i];
}
memset(dis, 0, sizeof(dis));
for (i = 1; i <= size; i++){
int d = (a[size+1-i]-i+size) % size;
dis[d]++;
}
for (i = 0; i < size; i++){
if (ans < dis[i])ans = dis[i];
}
cout << size-ans << endl;
}
int main(){
freopen("in.txt", "r", stdin);
int neibor[50005][2];
int i;
cin >> size;
for (i = 1; i <= size; i++){
scanf("%d%d",&neibor[i][0],& neibor[i][1]);
}
bool used[50005];
memset(used, 0, sizeof(used));
a[1] = 1;
used[1] = true;
for (i = 2; i <= size; i++){
int last = a[i - 1];
if (!used[neibor[last][0]]){
a[i] = neibor[last][0];
used[a[i]] = true;
}
else if (!used[neibor[last][1]]){
a[i] = neibor[last][1];
used[a[i]] = true;
}
else {
cout << -1 << endl;
return 0;
}
}
if (neibor[1][0] != a[size] && neibor[1][1] != a[size]){
cout << -1 << endl;
return 0;
}
go();
return 0;
}
0
回复 3516发表于2014-07-30 08:59
include<stdio.h>
include<string.h>
int data[50001][2],shi[50001],a[50001];
int main()
{
int n,i,j,qian,hou; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d%d",&data[i][0],&data[i][1]); } a[1]=1;shi[a[1]]=1 for(i=2;i<=n;i++) { qian=data[a[i-1]][0]; hou=data[a[i-1]][1]; if(shi[qian]==0) { a[i]=qian; shi[qian]=1; } else if(shi[hou]==0) { a[i]=hou; shi[hou]=1; } else { printf("-1"); return 0; } } int temp=0,max=0; memset(shi,0,sizeof(shi)); for(i=1;i<=n;i++) { temp=(n+a[i]-i+1)%n; shi[temp]++; } for(i=0;i<n;i++) { if(max<shi[i]) { max=shi[i]; } } memset(shi,0,sizeof(shi)); for(i=1;i<=n;i++) { temp=(n+a[n-i+1]-i+1)%n; shi[temp]++;
}
for(i=0;i<n;i++)
{
if(max<shi[i])max=shi[i];
}
printf("%d",n-max);
}
0
回复 S.Y.F发表于2013-08-31 14:04
题解
1111111129回复于2014-08-13 11:52
orzorzorz
0
回复 S.Y.F发表于2013-07-29 16:55
从10、到30、到100。。。。。。
题解:http://blog.163.com/syf_light_feather/blog/static/223755067201362945326756/
0
回复 vcvycy发表于2013-06-30 00:56
20 30 40 50 70 分都有~泪流满面.
Accepted
100
772 2
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:55:05
Wrong Answer
70
613 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:53:24
Wrong Answer
70
686 2
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:45:35
Wrong Answer
70
856 2
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:42:12
Wrong Answer
70
803 2
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:37:26
Wrong Answer
70
882 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:22:39
Wrong Answer
70
1145 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:20:30
Wrong Answer
10
733 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:11:30
Wrong Answer
50
723 1
P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:04:20
Wrong Answer
50
781 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:55:49
Wrong Answer
40
656 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:49:49
Wrong Answer
40
758 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:44:00
Time Exceeded
30
7160 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:38:22
Time Exceeded
20
7135 1
P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:35:08
0
回复 SEX丶Elope发表于2013-02-16 10:10
点击查看程序源码+详细题解
cuichen回复于2014-09-09 09:24
怎么又是你??你有什么企图?骗访问量???垃圾!
0
回复 qyjubriskxp发表于2010-07-09 21:31
再一次体会到c++流的悲剧,秒杀和3s原来只是输入方式的不同,杯具~~
yuyilahanbao回复于2014-01-24 11:47
从c转到c++第一次不AC(除去忘记把语言有c改为c++的)就是因为c++输入输出的问题
从那次起,我的c++的输入都是用scanf和printf了
因为
保险
安全
我记不清cin是<<还是>>
printf和scanf相对更灵活
....
0
回复 slm发表于2010-03-16 18:27
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
嘿嘿
0
回复 superyoi发表于2009-11-10 11:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
superyoi killed p1008 with a headshot by awp
0
回复 200853349发表于2009-11-10 10:49
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
当我看到众位神牛打出“置换群”三个字后,我在黑书百度GOOGLE维基百科逛了得有一个半小时多然后回来AC了。。。
思路和strini神牛的基本一样。
0
回复 sinb发表于2009-11-09 13:02
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
其实很简单,不要想复杂了,先是想办法构成,然后用置换群的方法即可ac。
0
回复 香蕉派发表于2009-11-06 11:29
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
虽然不懂什么叫置换群,但是思路还是很清晰的。。
0
回复 赏金神侠PPF发表于2009-11-05 11:45
一星星纪念~
0
回复 strini发表于2009-10-30 22:11
根据群论原理,任何置换群都可以分解为若干个循环节。显然,这道题目就是冲着这点来的。因为如果某循环的长度为L,那么本题中只需要代价为L的操作。注意,这里的L!=1,这是因为只有一个人的循环节不需要任何代价的操作。到这里才只能拿三十分,因为圈是可以旋转的,常规方法需要O(n^2)才能解决。不妨这里以编号为1的人为基准,定义每个人到自己应该所在位置的距离。距离不超过n-1。可以通过最大值来寻找能在自己位置上的最多的人数(因为距离为x的人在旋转x次后转到自己的位置上),那么在比较好的情况下,可以优化到O(n)。
TIME: 1H
SUBMIT:
1 70 Error: 发现希望相邻是不精确的,于是改了个搜索方向。(以为题目给定的是按照左右方向,白书说过不能“假定”!)。
2 90 Error: 终于明白要取两个搜索方向的最大值。
3 Accepted.
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 skykey发表于2009-10-29 17:58
include<iostream>
using namespace std;
int n;
int a[50001],b[50001],c[50001];
int aim[50001];
void G_MAP()
{
bool mark[50001]={false};
int p=1,r=1;
while(p<=n)
{
aim[p]=r;mark[r]=true;p++;
if(!mark[a[r]])r=a[r];
else if(!mark[b[r]])r=b[r];
else if(p<=n){cout<<-1;exit(0);}
}
}
int COMPULATE()
{
int max=0;
int t;
int record[2][50001];
for(int i=1;i<=n;i++)record[0][i]=record[1][i]=0;
for(int i=1;i<=n;i++)
{
if((t=aim[i]-i)<0)t+=n; record[0][t]++; if(record[0][t]>max)max=record[0][t];
if((t=aim[i]-(n+1-i))<0)t+=n; record[1][t]++; if (record[1][t]>max)max=record[1][t];
}
return max;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{scanf("%d%d",&a[i],&b[i]);c[a[i]]++;c[b[i]]++;}
for(int i=1;i<=n;i++)if(c[i]!=2){cout<<-1;return 0;}
G_MAP();
int T=COMPULATE();
cout<<n-T;
}
0
回复 song19931218发表于2009-10-27 20:11
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
考虑两种情形(貌似这两种情形很像,但又真的不同,后来才想起,在化学的手性碳原子那部分遇到过类似情况。。。)
然后就是运用置换群的知识
0
回复 Aries_C发表于2009-10-25 08:24
正反两遍...两遍...<幽幽的声音飘远..>
不然就是70分啊...
不看题解的情况下竟然自己想到了...
记得以前老师给我们做过这题的..细节什么的现在做又忘记了..唉..
0
回复 国防安全员001发表于2009-10-21 22:00
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1701人
提交 4835次
通过率 35%
难度 3
题目表述有问题。。
0
回复 liubosen发表于2009-10-21 21:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
yaaaayyayayyayayayayayayayayayayayayayayayyaayayayayayayyaayayayay
var
n,max,i:longint;
a,b,c,d:array[0..50001] of longint;
begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
c[1]:=1;
c[2]:=a[1];
for i:=3 to n do
if c=a[c] then c[i]:=b[c]
else
if c=b[c] then c[i]:=a[c]
else begin
writeln(-1);
halt
end;
if c[n]<>b[1] then
begin
writeln(-1);
halt
end;
fillchar(d,sizeof(d),0);
for i:=1 to n do
inc(d[(c[i]-i+n)mod n]);
for i:=0 to n-1 do
if d[i]>max then max:=d[i];
fillchar(d,sizeof(d),0);
for i:=1 to n do
inc(d[(c[i]+i-1)mod n]);
for i:=0 to n-1 do
if d[i]>max then max:=d[i];
writeln(n-max);
end.
0
回复 lishunzhi发表于2009-10-21 00:11
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
置换群,但建环是重点
0
回复 zebra发表于2009-10-03 09:48
include <iostream> include <cassert>
using namespace std;
long N,seq[50001],p=1;
class
{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2)
{
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2)
return true;
return false;
}
public:
bool AddE(long v1,long v2)
{
if(isnbr(v1,v2))
return true;
else
if(nbr[v1][0]==2||nbr[v2][0]==2)
return false;
else
{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i)
{
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++)
{
if(!flag[nbr[i][j]])
{
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve()
{
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N; b=seq[i]-(N+1-i); if(b<0) b+=N; if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main()
{
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++)
{
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2))
{
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
system("pause");
return 0;
}
0
回复 -117-Join发表于2009-09-18 21:29
哪位大牛帮忙看看我错哪里了
它只得90分
program fire;
type
arr=record
l,r:longint;
end;
var
num:array[1..50000]of longint;
a:array[1..50000]of arr;
b:array[1..50000]of longint;
i,k,j,n:longint;
begin
readln(n);
for i:=1 to n do
readln(a[i].l,a[i].r);
b[1]:=1;
b[n]:=a[1].l;
if a[b[n]].l=b[1]then b[n-1]:=a[b[n]].r
else b[n-1]:=a[b[n]].l;
i:=n-1;
b[2]:=a[1].r;
j:=2;
while j<=i do
begin
if b<>a[b[i]].l then b:=a[b[i]].l
else b:=a[b[i]].r;
dec(i);
if b[j-1]<>a[b[j]].r then b[j+1]:=a[b[j]].r
else b[j+1]:=a[b[j]].l;
inc(j);
end;
for i:=2 to n-1 do
if(b<>a[b[i]].r)and(b<>a[b[i]].l)or(b<>a[b[i]].r)and(b<>a[b[i]].l)then
begin
write(-1);
halt
end;
if(b[n]<>a[b[1]].l)and(b[n]<>a[b[1]].r)or(b[2]<>a[b[1]].l)and(b[2]<>a[b[1]].r)or(b[1]<>a[b[n]].l)and(b[1]<>a[b[n]].r)or(b[n-1]<>a[b[n]].l)and(b[n-1]<>a[b[n]].r)then
begin
write(-1);
halt
end;
num[0]:=0;
for i:=1 to n do
begin
a[b[i]].l:=i;
num[i]:=0;
end;
for i:=1 to n do
if a[i].l-i>=0 then inc(num[a[i].l-i])
else inc(num[a[i].l-i+n]);
j:=0;
for i:=0 to n do
if num[i]>j then j:=num[i];
write(n-j);
end.
写的有点长
0
回复 fs302发表于2009-09-17 20:13
分析:学一个好思想:正难则反!由顺序到乱序我们很难快速找到,但是我们知道如何从乱序变为顺序!解决本题利用了组合数学中置换群的思想。
从第一个人处断开,将圆环的问题转化为序列的问题。如果可以,求出目标序列。求出目标序列复杂度O(n).
求出目标序列右移0至n-1位置时,不需要移动的人数。将目标序列反转,再求出目标序列右移0至n-1位置时,不需要移动的人数。求不需要移动的人数最大等价于求需要移动的人数最小。复杂度O(n)。
更详细的说:
引进“相对有序”这个概念,当两个人满足C[j]-C[i]==j-i时,两个相对有序。
题目要求最小的总代价,但是我们可以考虑倒过来想,要求最小的总代价亦即求最多有多少人不用移动,亦即相对有序。
然后我们引进一个辅助变量T=C-I,{C-I>=0},T=C[i]-I+N,{C[i]-I<0},那么这个T[i]有什么意义呢?我们知道初始状态的编号是1-N,而目标状态是C[1]-C[N],那么C-I便是从目标状态到初始状态顺时针所要移动的距离,那么如果那么T值相等的两个同学则是相对有序的,亦即不用移动,我们只要找出最大的T然后N-Max(T)就是得到的结果,但是这样还不够,因为刚刚那样只是顺时针所要移动的距离,我们还要计算逆时针的到的结果,从顺时针和逆时针中找到最大的T,然后N-Max(T)才能够是正确结果.
0
回复 maxint64发表于2009-09-01 21:33
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
先是物理大发了——以为 b1,b2...bm是连续的
看了牛们的题解 一次ac :)
0
回复 柔情使者发表于2009-08-20 15:44
第一遍做的时候没有看题解,自己测了好几遍总是60分,看了n多大牛的解释才恍然大悟,竟然要正反两遍!!!唉,幸亏咱有测试数据,否则我可就惨了...
O(n)的求目标队列算法,都说是冒泡排序,我没看出来,倒是有点像。
0
回复 maxiem发表于2009-08-18 20:55
物理自重啊,嘿嘿。
注意要正反两遍哦~
9MS?
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 9ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:9ms
(好像那个冒泡是口胡,大家不要被那个蒙了
program fire;
var
st:array [1..50000,1..2] of longint;
k,final:array [0..50000] of longint;
ex:array [1..50000] of boolean;
p,max,i,n:longint;
begin
fillchar (st,sizeof(st),0);
fillchar (ex,sizeof(ex),0);
fillchar (final,sizeof(final),0);
fillchar (k,sizeof(k),0);
readln (n);
for i:=1 to n do readln (st,st);
final[1]:=1;p:=2;ex[1]:=true;
for i:=1 to n do begin
if ex[st[final[i],1]]=false then begin
final[p]:=st[final[i],1];
ex[st[final[i],1]]:=true;
inc(p);
end
else if ex[st[final[i],2]]=false then begin
final[p]:=st[final[i],2];
ex[st[final[i],2]]:=true;
inc(p);
end;
end;
if p-1<>n then begin
writeln (-1);
halt;
end;
max:=0;
for i:=1 to n do if final[i]>=i then inc(k[final[i]-i]) else inc(k[n-i+final[i]]);
for i:=0 to n-1 do if k[i]>max then max:=k[i];
fillchar (k,sizeof(k),0);
for i:=n downto 1 do if final[i]>=n-i+1 then inc(k[final[i]-n+i-1]) else inc(k[final[i]+i-1]);
for i:=0 to n -1 do if k[i]>max then max:=k[i];
writeln (n-max);
end.
0
回复 suning发表于2009-08-14 09:43
啊呜~
一年前误解了题意~
一年后理解了题意~
然后就是1次美妙的AC
PS:[误]解[理]解~~~[物理]?
0
回复 fengwuliu发表于2009-08-13 17:20
lgxcgd说的太对了!太感谢了5555
0
回复 Matt发表于2009-08-11 22:28
NOIP也会考高等数学...
由于原图是环,所以置换群可表示为一次循环。作差是个好方法。
但求冒泡排序是怎么作的
0
回复 3830372发表于2009-08-11 21:28
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1504人
提交 4282次
通过率 35%
难度 3
提交 讨论 题解 状态
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 尖端才子发表于2009-08-11 11:14
纪念一下……第1500个AC……
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1500人
提交 4274次
通过率 35%
难度 3
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 SecretAgent发表于2009-08-10 14:02
置换群是正解
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 yangbei发表于2009-08-07 14:57
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 338ms
├ 测试数据 05:答案正确... 322ms
├ 测试数据 06:答案正确... 306ms
├ 测试数据 07:答案正确... 338ms
├ 测试数据 08:答案正确... 338ms
├ 测试数据 09:答案正确... 322ms
├ 测试数据 10:答案正确... 306ms
Accepted 有效得分:100 有效耗时:2270ms
算镜像时偷了点懒,不过也算一遍AC了
0
回复 ja_son发表于2009-08-06 15:44
a:拆环成队,寻求目标队列。
b:b1,b2...bm不是连续的,而且是任意的。只要有成立目标队列,与原来的队列相匹配就可以知道有多少(设为n个)需要移动位置,则代价就是n。
c:目标队列有多种情况,可以反转,也可以左右移动。
0
回复 1s发表于2009-08-03 17:56
如对本题有疑问可以参看我的题解:
http://xujieqi.blog.hexun.com/35722312_d.html
0
回复 DMKaplony发表于2009-07-30 15:15
当时的时间限制好像是2s。。有个题解说把1定为第一项然后进行冒泡排序。。不过这里是1s 啊。。。也行只有置换群了吧。
0
回复 xusc_2009发表于2009-07-28 14:30
看不懂,只好搁浅
什么时候想清楚了再做
0
回复 董发表于2009-07-24 19:11
program p1008;
var i,n,k,j,sum1,sum2,ans,max:longint;
a,b,w,d,c:array[0..50005] of longint;
begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
w[1]:=1; w[2]:=a[w[1]];
k:=1;
repeat
inc(k);
if w[k-1]=a[w[k]] then w[k+1]:=b[w[k]]
else if w[k-1]=b[w[k]] then w[k+1]:=a[w[k]]
else begin
writeln(-1);
exit;
end;
until k=n;
if w[n+1]<>w[1] then
begin
writeln(-1);
exit;
end;
for i:=1 to n do
begin
a[i]:=w[i]-i;
b[i]:=w[n-i+1]-i;
if a[i]<0 then a[i]:=a[i]+n;
if b[i]<0 then b[i]:=b[i]+n;
inc(c[a[i]]);
inc(d[b[i]]);
end;
for i:=0 to n-1 do
begin
if ans<c[i] then ans:=c[i];
if ans<d[i] then ans:=d[i];
end;
writeln(n-ans);
end.
0
回复 我飞发表于2009-07-23 21:00
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 93狒狒发表于2009-07-23 20:59
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
秒杀......
0
回复 fjxmlhx发表于2009-07-22 13:15
置换群,做2n次,顺时针和逆时针.
对于一个置换,最小操作费用是所有循环长度的和.因此实际上是找出2n个置换中哪个置换循环长度为1的数量最多.
0
回复 340508965发表于2009-07-21 15:01
⊙﹏⊙b汗
不知道的以为这是数学竞赛......
...
我的数论与图论可以说脑袋里空白一片.........
怎么办,我的竞赛啊
........
算了 看了题解 大家写的
总算弄懂这道题了
先前以为b1,b2,b3..bm是连续的
没想到是任意的!!!!!!!!!
诶 叹悲歌未切 为撼奈何编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
总算AC了
program p1008;
var i,n,k,j,sum1,sum2,ans,max:longint;
a,b,w,d,c:array[0..50005] of longint;
begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
w[1]:=1; w[2]:=a[w[1]];
k:=1;
repeat
inc(k);
if w[k-1]=a[w[k]] then w[k+1]:=b[w[k]]
else if w[k-1]=b[w[k]] then w[k+1]:=a[w[k]]
else begin
writeln(-1);
exit;
end;
until k=n;
if w[n+1]<>w[1] then
begin
writeln(-1);
exit;
end;
for i:=1 to n do
begin
a[i]:=w[i]-i;
b[i]:=w[n-i+1]-i;
if a[i]<0 then a[i]:=a[i]+n;
if b[i]<0 then b[i]:=b[i]+n;
inc(c[a[i]]);
inc(d[b[i]]);
end;
for i:=0 to n-1 do
begin
if ans<c[i] then ans:=c[i];
if ans<d[i] then ans:=d[i];
end;
writeln(n-ans);
end.
0
回复 zsy90943发表于2009-07-18 00:51
构造巧妙、、看来还是要学好数论和图论额、、、、
0
回复 POM无敌牛B发表于2009-07-16 11:47
编译通过...
├ 测试数据 01:运行超时...
├ 测试数据 02:运行超时...
├ 测试数据 03:运行超时...
├ 测试数据 04:运行超时...
├ 测试数据 05:运行超时...
├ 测试数据 06:运行超时...
├ 测试数据 07:运行超时...
├ 测试数据 08:运行超时...
├ 测试数据 09:运行超时...
├ 测试数据 10:运行超时...
Unaccepted 有效得分:0 有效耗时:0ms
无奈 哪位哥哥救救我
0
回复 yxy发表于2009-06-16 18:16
把置换解释成度为2图,真有才.
求出序列,正反分别做一次差就行了.
0
回复 sxpeter发表于2009-06-14 16:56
讲建环吧。数组w表示环,我用的是一种类似并查集的方法。
begin
read(n);
for i:=1 to n do read(a[i],b[i]);
t:=2;w[1]:=1;w[2]:=a[1];
while true do begin
if a[w[t]]<>w[t-1]then w[t+1]:=a[w[t]]//是否在左边
else if b[w[t]]<>w[t-1]then w[t+1]:=b[w[t]]//是否在右边
else begin writeln(-1);halt;end;//失败判断
inc(t);
if t>n then break;
end;
if w[n+1]<>w[1]then begin writeln(-1);halt;end;//本句一定要加!!!!!!
end.
0
回复 lgxcgd发表于2009-05-17 20:24
首先把这个圈看做一个图,每个同学看做一个顶点。因为要形成环,所以每个顶点的度必须为2。
如果存在度数不为2的顶点,那么整个图无法构成一个环,即“无论怎么调整都不能符合每个同学的愿望”输出-1。
如果是一个环,那么就遍历图,生成以第1个顶点为开头的序列。现在就要求出最小移动的代价。
在理解题意所述的调整方式中,要注意实际上就是把M个在错误位置上的人移动到正确的位置上,代价为M。一次下令移动即可。
假如生成的目标序列为1,5,3,2,4。我们现在就需要比较它和初始状态1,2,3,4,5,看有几个人离开了原来的位置。但这个序列实际代表的是一个环,而且方向正反有两种,就需要把初始序列正反分别转N次,和得到的序列比较,看其中最少有几个位置上的人编号不相同,就得到了我们要求的最小代价。
上述方法有大量冗余。但可以发现转来转去不管怎么转,任意两个人之间的相对位置关系在这过程中都不会变。于是想到做差,如果差小于0则加上N。
1 5 3 2 4
- 1 2 3 4 5
0 3 0 3 4
这表示序列1,5,3,2,4不转动时1,3两个人在原来的位置上,转动3个位置后5和2两个人在原来的位置上,转动4个位置后只有4一个人会在原来的位置上。这就是说,1,5,3,2,4与1,2,3,4,5在旋转后最多有2个位置上的人编号相同,即最少有3个位置上的人编号不相同。同理要反转再求一次。
记录每个不同的差值的个数,取其最大值P,即不调换次数最大的。结果N-P就是调换次数最小的。
0
回复 src250发表于2009-05-14 08:27
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
切记:重新构图时一定要对数组清空!我的第一次只有50分,就是这个原因!
0
回复 love19960108发表于2009-04-26 17:59
这题可以用C++这样做么??
include <iostream> include <cassert>
using namespace std;
long N,seq[50001],p=1;
class{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2){
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2) return true;
return false;
}
public:
bool AddE(long v1,long v2){
if(isnbr(v1,v2)) return true;
else if(nbr[v1][0]==2||nbr[v2][0]==2) return false;
else{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i){
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++){
if(!flag[nbr[i][j]]){
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve(){
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N; b=seq[i]-(N+1-i); if(b<0) b+=N; if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main(){
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++){
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2)){
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
return 0;
}
0
回复 voyagec2发表于2009-03-18 15:53
难理解,不过算法很精妙
0
回复 pRoevollove发表于2009-02-25 23:49
天,把(p[i]-i+n)mod n理所当然地打成了abs(p[i]-i)
结果一直50分……还一直以为自己构造错了……
ps 我可以过楼下的范例哦
0
回复 ufo172849z发表于2009-01-24 23:05
ms楼下的程序不能处理这种反例(测试数据还是不够强啊)
6
2 3
1 3
1 2
5 6
4 6
4 5
应该输出-1的吧?因为是两个环
var a,b:array[0..50000]of longint;
c:array[0..50000,1..2]of longint;
d:array[0..50000]of boolean;
i,j,k,m,n,max:longint;
can:boolean;
begin
readln(n);
for i:=1 to n do
readln(c,c);
b[0]:=c[1,1]; b[n]:=c[1,1];
fillchar(d,sizeof(d),0);
k:=1;
can:=true;
for i:=1 to n-1 do
begin
if d[k] then can:=false;
b[i]:=k; d[k]:=true;
if b=c[k,1] then k:=c[k,2]
else if b=c[k,2] then k:=c[k,1]
else can:=false;
if not can then break;
end;
if can then
if b[n]<>k then can:=false;
if can then
begin
max:=-1;
fillchar(a,sizeof(a),0);
for i:=1 to n do
inc(a[(b[i]-i+n) mod n]);
for i:=0 to n-1 do
if a[i]>max then max:=a[i];
fillchar(a,sizeof(a),0);
for i:=1 to n do
inc(a[(b[n-i+1]-i+n)mod n]);
for i:=1 to n-1 do
if a[i]>max then max:=a[i];
writeln(n-max);
end
else
writeln(-1);
end.
0
回复 tangdongjian发表于2009-01-23 22:17
我在做镜像时把原先max直接覆盖上了,注意
0
回复 永恒888发表于2009-10-26 22:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 tangkunjie发表于2009-06-04 19:50
挺烦人的题目
0
回复 ykspeter发表于2008-11-13 20:32
program fire(input,output);
var
n,i,j,k,max,v:longint;
a:array[0..100000,1..2] of longint;
b,c:array[0..100000] of longint;
begin
readln(n);
for i:=1 to n do readln(a,a);
for i:=1 to n do
begin
k:=0;
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if (k=4) or (k=3)
then begin
writeln('-1');
exit
end
end;
b[1]:=1;i:=2;k:=a[1,1];j:=1;
repeat
b[i]:=k;
inc(i);
v:=k;
if a[k,1]<>j
then k:=a[k,1]
else k:=a[k,2];
j:=v;
until i=n+1;
fillchar(c,sizeof(c),0);
for i:=1 to n do inc(c[(b[i]-i+n)mod n]);
for i:=0 to n-1 do
if c[i]>max
then max:=c[i];
fillchar(c,sizeof(c),0);max:=0;
for i:=1 to n do inc(c[(b[n-i+1]-i+n)mod n]);
for i:=n-1 downto 0 do
if c[i]>max
then max:=c[i];
writeln(n-max);
end.
0
回复 getuojian发表于2008-11-10 13:38
include<stdio.h> include<memory.h>
const int maxn=50010;
int n;
int f[maxn][2];
int goal[maxn];
int ans=maxn;
int hash[maxn];
bool SET_ORI(){
bool flag[maxn];
memset(flag, true, sizeof(flag));
goal[1]=1; flag[1]=false;
for (int i=1; i<=n-1; i++){
if (flag[f[goal[i]][0]]){
goal=f[goal[i]][0];
flag[f[goal[i]][0]]=false;
continue;
}
if (flag[f[goal[i]][1]]){
goal=f[goal[i]][1];
flag[f[goal[i]][1]]=false;
continue;
}
return false;
}
if ((goal[n]!=f[1][0]) && (goal[n]!=f[1][1]))
return false;
return true;
}
int SWAP(int i, int j){
int t=goal[i];
goal[i]=goal[j];
goal[j]=t;
return 0;
}
int min(int i, int j){
return i>j?j:i;
}
int HASH(){
for(int i=1; i<=n; i++)
hash[i]=goal[i]-i+n;
return 0;
}
int CALC(){
int temp[maxn2], back=0;
memset(temp, 0, sizeof(temp));
for (int i=1; i<=n; i++)
temp[hash[i]%n]++;
for (int i=1; i<=2n-1; i++)
if (temp[i] > back)
back=temp[i];
return back;
}
int main(){
freopen("fire.in", "r", stdin);
freopen("fire.out", "w", stdout);
scanf("%d", &n);
for (int i=1; i<=n; i++)
scanf("%d %d", &f[i][0], &f[i][1]);
if (!SET_ORI()){
printf("-1");
return 0;
}
//forward
HASH();
ans=min(ans, n-CALC());
//backward
for (int i=1; i<=n/2; i++)
SWAP(i,n-i+1);
HASH();
ans=min(ans, n-CALC());
printf("%d", ans);
return 0;
}
0
回复 IVORY发表于2008-11-06 10:46
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
CHEAT的...
0
回复 storey p发表于2008-11-05 14:19
回447389831:
exit换成halt
0
回复 FenXy发表于2008-11-04 08:28
艺术p245
0
回复 hlq发表于2008-11-01 14:31
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
求不在位置上的人数
a【i】 第i位上的同学编号
for i:=1 to n do
begin
inc(b[(a[i]-i+n) mod n])
end;
max:=0;
for i:=0 to n-1 do
if b[i]>max then max:=b[i];
fillchar(b,sizeof(b),0);
for i:=1 to n do
begin
inc(b[(a[i]-(n-i+1)+n)mod n]);//对称
end;
for i:=0 to n-1 do
if b[i]>max then max:=b[i];
0
回复 Will~骷髅发表于2008-10-30 21:37
编译通过...
├ 测试数据 01:运行超时...
├ 测试数据 02:运行超时...
├ 测试数据 03:运行时错误...|错误号: -1073741819
├ 测试数据 04:运行时错误...|错误号: -1073741819
├ 测试数据 05:运行时错误...|错误号: -1073741819
├ 测试数据 06:运行时错误...|错误号: -1073741819
├ 测试数据 07:运行时错误...|错误号: -1073741819
├ 测试数据 08:运行时错误...|错误号: -1073741819
├ 测试数据 09:运行时错误...|错误号: -1073741819
├ 测试数据 10:运行时错误...|错误号: -1073741819
Unaccepted 有效得分:0 有效耗时:0ms
怎么会这样???
0
回复 悲伤逆流成河发表于2008-10-28 22:13
include <iostream> include <fstream>
using namespace std ;
int hash[50001];
int n , i , j , t , maxs(0) ;
inline void HASH ( int e[] )
{
for ( i = 1 ; i <= n ; i++ )
{
e[i] -= i ;
if ( e[i] < 0 ) e[i] += n ;
hash[e[i]]++ ;
}
for ( i = 0 ; i < 50001 ; i++ )
if ( maxs < hash[i] ) maxs = hash[i] ;
}
int main(){
ifstream fin ("fire.in") ;
ofstream fout ("fire.out") ;
fin >> n ;
int e[n+1] , h[n+1][2] , e2[n+1];
bool f[n+1] ;
for ( i = 1 ; i <= n ; i++ )
{
f[i] = false ;
fin >> h[i][0] >> h[i][1] ;
}
e[1] = 1 ;
f[1] = true ;
for ( i = 2 ; i <= n ; i++ )
{
if ( e < 0 ) { fout << -1 << endl ; exit(0) ; }
if ( !f [ h[ e ][0] ] ) e[i] = h[ e ][0] ;
if ( !f [ h[ e ][1] ] ) e[i] = h[ e ][1] ;
f[ e[i] ] = true ;
}
for ( i = 1 , j = n ; i <= n ; i++,j-- ) e2[j] = e[i] ;
HASH ( e ) ;
memset ( hash , 0 , sizeof ( hash ) ) ;
HASH ( e2 ) ;
fout << n - maxs << endl ;
}
0
回复 evelynhe发表于2008-10-26 16:31
“置换群思想...今天刚明白...
先构造新数列(要构造两次,否则只有70分),然后向右计算相对位置差,然后累加记录数组,然后用N减去相对位置差累加值最大的,就是答案... ”
这是真的
0
回复 true1023发表于2008-10-25 09:32
置换群的基本概念
利用原序列和目标序列每个元素的绝对位置差来求出原序列每个元素对于目标序列的相对位置,找相对位置相同的最多的元素数,用总元素数减去它即为结果。
0
回复 447389831发表于2008-10-21 09:45
program fire(input,output);
var
n,i,j,k,max,v:longint;
a:array[0..100000,1..2] of longint;
b,c:array[0..100000] of longint;
begin
readln(n);
for i:=1 to n do readln(a,a);
for i:=1 to n do
begin
k:=0;
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if (k=4) or (k=3)
then begin
writeln('-1');
exit
end
end;
b[1]:=1;i:=2;k:=a[1,1];j:=1;
repeat
b[i]:=k;
inc(i);
v:=k;
if a[k,1]<>j
then k:=a[k,1]
else k:=a[k,2];
j:=v;
until i=n+1;
fillchar(c,sizeof(c),0);
for i:=1 to n do inc(c[(b[i]-i+n)mod n]);
for i:=0 to n-1 do
if c[i]>max
then max:=c[i];
fillchar(c,sizeof(c),0);max:=0;
for i:=1 to n do inc(c[(b[n-i+1]-i+n)mod n]);
for i:=n-1 downto 0 do
if c[i]>max
then max:=c[i];
writeln(n-max);
end.
90 分,牛人门帮看下把
0
回复 cnfnje1发表于2008-10-17 18:12
置换群.....是什么?
readln(n);
for i:=1 to n do readln(a[i],b[i]);
c[1]:=1; c[2]:=a[1];
for i:=3 to n do if c=a[c] then c[i]:=b[c]
else if c=b[c] then c[i]:=a[c]
else begin writeln(-1); halt end;
if c[n]<>b[1] then begin writeln(-1); halt end;
fillchar(d,sizeof(d),0);
for i:=1 to n do inc(d[(c[i]-i+n)mod n]);
for i:=0 to n-1 do if d[i]>m then m:=d[i];
fillchar(d,sizeof(d),0);
for i:=1 to n do inc(d[(c[i]+i-1)mod n]);
for i:=0 to n-1 do if d[i]>m then m:=d[i];
writeln(n-m);
是么?
0
回复 lyrics发表于2008-10-12 19:55
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
技巧性比较强吧,楼下不必构造2次,计算时从头至尾算一次,再倒过来算一次就行了
0
回复 LV.唱响发表于2008-10-05 08:38
置换群思想...今天刚明白...
先构造新数列(要构造两次,否则只有70分),然后向右计算相对位置差,然后累加记录数组,然后用N减去相对位置差累加值最大的,就是答案...
0
回复 宇智波带波斯猫发表于2008-10-05 08:33
Flag Accepted
题号 P1008
类型(?) 其它
通过 1065人
提交 3000次
通过率 35%
难度 3
第3000个提交的
0
回复 鸳鸯羡发表于2008-09-28 18:19
include <iostream>
using namespace std ;
int hash[50001];
int n , i , j , t , maxs(0) ;
inline void HASH ( int e[] )
{
for ( i = 1 ; i <= n ; i++ )
{
e[i] -= i ;
if ( e[i] < 0 ) e[i] += n ;
hash[e[i]]++ ;
}
for ( i = 0 ; i < 50001 ; i++ )
if ( maxs < hash[i] ) maxs = hash[i] ;
}
int main(){
cin >> n ;
int e[n+1] , h[n+1][2] , e2[n+1];
bool f[n+1] ;
for ( i = 1 ; i <= n ; i++ )
{
f[i] = false ;
cin >> h[i][0] >> h[i][1] ;
}
e[1] = 1 ;
f[1] = true ;
for ( i = 2 ; i <= n ; i++ )
{
if ( e < 0 ) { cout << -1 << endl ; exit(0) ; }
if ( !f [ h[ e ][0] ] ) e[i] = h[ e ][0] ;
if ( !f [ h[ e ][1] ] ) e[i] = h[ e ][1] ;
f[ e[i] ] = true ;
}
for ( i = 1 , j = n ; i <= n ; i++,j-- ) e2[j] = e[i] ;
HASH ( e ) ;
memset ( hash , 0 , sizeof ( hash ) ) ;
HASH ( e2 ) ;
cout << n - maxs << endl ;
}
80分
0
回复 月光疾风发表于2008-09-25 13:03
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
纪念我第200次提交!过第79题。。。。
0
回复 ghostplant发表于2008-09-20 19:48
include <iostream> include <fstream> include <cassert>
using namespace std;
long N,seq[50001],p=1;
class{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2){
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2) return true;
return false;
}
public:
bool AddE(long v1,long v2){
if(isnbr(v1,v2)) return true;
else if(nbr[v1][0]==2||nbr[v2][0]==2) return false;
else{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i){
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++){
if(!flag[nbr[i][j]]){
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve(void){
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N; b=seq[i]-(N+1-i); if(b<0) b+=N; if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main(){
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++){
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2)){
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
return 0;
}
0
回复 zzh19950802发表于2008-09-17 19:29
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案错误... ├ 标准行输出
├ 错误行输出
├ 测试数据 05:答案错误... ├ 标准行输出
├ 错误行输出
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 462ms
├ 测试数据 08:答案正确... 369ms
├ 测试数据 09:答案正确... 384ms
├ 测试数据 10:答案错误...程序输出比正确答案长
为什么我的程序不对?
include <iostream>
using namespace std;
define MAXN 50000
int man[MAXN+2][2];
int cercle[MAXN+2]={0,1};
int used[MAXN+2]={0};
int reduce[2][MAXN+2]={0};
int n;
int main()
{
long i,p,q=1,t;
int max=0;
cin>>n;
for (i=1;i<=n;i++) cin>>man[i][0]>>man[i][1];
p=man[q][1];
for (i=2;i<=n+1;i++)
{
if (man[q][1]==p)
{
p=q;
q=man[q][0];
}
else
{
if(man[q][0]!=p) break;
p=q;
q=man[q][1];
}
if(used[q]) break;
else used[q]=1;
cercle[i]=q;
}
if (i<=n+1) cout<<-1;
else
{
for (i=1;i<=n;i++)
{
if((t=cercle[i]-i)<0) t+=n; reduce[0][t]++; if (reduce[0][t]>max) max=reduce[0][t];
if ((t=cercle[i]-n+i-1)<0) t+=n; if (reduce[1][t]>max) max=reduce[1][t];
}
cout<<n-max;
}
return 0;
}
0
回复 liaorc发表于2008-09-16 17:56
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 cxy450090074发表于2008-09-04 13:34
oh no
0
回复 Lost.G发表于2008-08-22 15:49
我在想``怎么样才能不看错这题呢
0
回复 bonism发表于2008-08-14 21:30
时间复杂度O(N)。。。
原来我一直把题意理解错。。。囧!!。。
关于“置换群”,请看LRJ的《算法艺术与信息学竞赛》P245那一小节,还是比较好理解的。
0
回复 lemon_cn发表于2008-08-08 15:55
热烈庆祝用pascal AC的第二题~
p.s.我是C++的~~
0
回复 oipn4e2发表于2008-08-05 21:36
解决效率不高,但AC了。
0
回复 notblack发表于2008-08-01 09:17
用距离来分类,统计在原位的最大人数,奇怪的是
b[1]:=1;
b[2]:=a[1,1];
b[n]:=a[1,2];
建环的时候,上面的改成
b[1]:=1;
b[2]:=a[1,2];
b[n]:=a[1,1];
最后一个点却过不了,太奇怪了.
0
回复 332404521发表于2008-07-14 13:53
对于初三刚刚中考完的我,要理解这题的意思是万万不能的。。。
看题解我知道了应该怎么做,但那不是我的,所以不做了。。。
哪天能证明出来那啥再来做
0
回复 Sheeta发表于2007-11-14 15:45
好简单啊
直接贪啊
(P.S.置换群?什么东东...)
0
回复 mingyueyucai发表于2007-11-09 21:22
我代码写了老长老长,结果还是只过了8个点,有没有搞错?
我想请问一下,我和大家的一样,先排列出目标状态.然后确定初始状态时使得最多的人在目标位置上,然后交换.但是得到的答案总是偏大一点.
然后我又把所有可以使最多的人在原位目标位置上的可能都尝试了一编(包括正反两个目标状态),结果还是只能过8个点,有2个点死都过不了!
我的算法有什么问题吗?
0
回复 luanjiyang发表于2007-11-08 08:44
很委琐的说 我提交了8遍。。
0→0→10→10→10→10→70→AC
-||
0
回复 lonelycorn发表于2007-11-05 23:31
数论……好底歇的东西。
0
回复 gamejifan发表于2007-11-04 11:15
这题的叙述,让我误会了一年多。tzkq……3q..要早知道是这种意思早就ac了这题。。显然没什么大意思,看过组合数学或者学过群论的都懂。。ms跟polya计数法那个循环的意思。。
写的时候竟然因为交换的时候写错一个字母wa。我汗。
0
回复 Alexandria发表于2007-11-01 13:33
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
好强大的题啊,不看题解还真不会!
0
回复 clfhaha1234发表于2007-10-30 18:09
请问什么是置换群啊?可以讲讲吗?………………
0
回复 rleepas发表于2007-10-30 13:18
楼下都是正解?
......
0
回复 Ice_Msk发表于2007-10-18 20:35
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
什么是置换群?不知道。。。照样过。。。。
0
回复 junlonely发表于2007-10-18 20:13
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 江南不才发表于2007-10-11 16:19
排序法这里会超时~
比赛的时间是2S~~
这里是1S~~
(_)
0
回复 秒杀群众发表于2007-10-10 17:05
居然是置换群。。。
对了。。。什么是置换群...
上网查啊!!!
0
回复 southstarj1发表于2007-10-02 18:50
思想:
置换群。(相关知识自己查)
对于一组数据,按各人的意愿排出一个序列,
如果无法排出,就输出-1。
再将环状序列变成链状,则这个目标序列为一个置换群,
与原序列(按1到n的一列)满足:
交换的最少人数等于目标序列与原序列不重合的人数。
因为总共有2n个目标序列(正反各n种),都算一遍就行了。
步骤:
读入数据;
构造一个目标序列;
统计该序列中元素位置与该元素在原序列位置的差值(同一方向)为i{i ∈ [0, n)}的元素个数;
将该序列的反序统计一遍;
从这些数据中选取一个最大的值max;
输出n - max;
注意:
构造目标序列时判断能否构造的条件;
统计一次差值的复杂度是O(n);
统计差值的目的是求与原序列最多的重合人数;
0
回复 wangjin5发表于2007-09-19 22:38
好经典的题奥
确实有难度
0
回复 the_melody发表于2007-09-03 17:58
Accepted 有效得分:100 有效耗时:0ms
好经典的题奥
0
回复 richardxx发表于2007-08-22 17:36
下面程序是错的,不好意思,弄错地方了....
0
回复 sm-star发表于2007-08-21 15:18
题目所求就是每次进行连续交换的人数总和,这样,一个看似复杂的题目就变的异常的简单了!
0
回复 wasyyyy发表于2007-08-11 02:05
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
HOHO~~~看讨论的时候看到有人提到‘置换群’这个东西,突然想起来我刚买的一本组合数学上有这么一块东西,就拿过来看了。。。。
然后就出现上面的东西了。。。。置换群,本来想求轮换的,发现轮换比较多,还是找不参与交换的比较好记。。。。
优化的方法。。。我看了下好象不只一个人讲过了。。。而且似乎我跟他们的都一样(没仔细看)所以就不说了。。。效率是O(n)的。。不用建环。
0
回复 angieqiu发表于2007-08-10 22:49
怎么判断建环失败啊?我的程序虽然AC但总觉得方法很傻
0
回复 梦ぁ逍遥发表于2007-07-17 13:45
想到了用t[i]=b[i]-i表示环
却没想到镜像..
十分感谢visister
让我从90分中挣扎出来...
0
回复 visister发表于2007-06-01 00:12
首先明显地可以知道我们需要对于目标状态建立出一个环。如果无法建立这个环,那么结果一定是-1,当建立好环以后可以知道最小移动代价一定等于最少的不在目标位置上的人数。那么我们可以对目标环进行顺时针旋转1~n-1之中任意一个,答案就一定等于旋转中的不在自己位置上的人数最少的那样的环的状态。但是对于50000的数据,我们如果要将环旋转1~n-1次,那么总共加上判断不在自己位置上的人数时间复杂度为O(n^2),显然在限定时间内是无法出解的。因此我们进行逆向思维:不在自己位置上最少的人数就一定会等于总人数减去在自己位置上最多的人数(仔细想想),那么我们就将该问题转化为了求在自己的位置上最多的人数,这样一来,我们对初始目标环中每一个位置进行判断需要旋转多少次可以回到自己位置上,每一个人的选择都将映射到[0..n-1]的数组中,选取当中最大的情况就为所求,但是考虑到环可以反转,那么我们还需要将环再求一次镜像,就可以得到初始目标需要旋转多少次可以得到在自己位置上最多的人数的环的状态,最后通过总的人数减去它即为问题所求,时间复杂度为O(n);
0
回复 pyh119发表于2006-11-16 20:11
哪个人不小心失火了找我啊!!!
PS:我是安徽省芜湖市119接线员....
0
回复 maomingming发表于2006-11-06 18:40
考虑旋转后最多可能重合的情况,另要注意圈可以反过来
0
回复 qian5发表于2006-09-30 21:35
直接输出‘-1’有一个点过
0
回复 BambooLeaf发表于2006-09-26 18:17
见过的最牛最简单的方法……
将此题转换为冒泡排序,记录下所有交换的次数和两数间的距离,加上就行了……—__—|||
具体是这样的,我们反向思维,本来是要求一个有序数列求出成为无序数列的代价,现在我们把无序数列(即目标数列)进行冒泡排序,然后……就是这样……
看完之后,偶巨汗……
0
回复 xcjzj发表于2006-09-26 17:18
每组数据确定两组相对位置关系,并且这两组互为镜像。
对于某一种排列方式,不在需要位置上的人数即为当前状态到目标状态的最小代价。
先找出其中一种排列方式。由于目标状态可以通过旋转而使得部分人的变化次数减少,所以找出每个人通过某一固定方向旋转到达目标位置的旋转次数。找到某一次数,使得拥有这个次数的人数最多。那么,通过旋转这一最多人拥有的次数,即可使得尽可能多的人不通过交换直接到达目标位置。于是,不拥有这一旋转次数的人数即为这一状态下的最小代价。
然后,用现在的目标状态找出其镜像状态,并且用上述方法再找一遍最小代价,与前面的结果比较,较小值即为答案。
另外,题目中会出现一些无解的情况:
1.某个人被“要”的次数多于两次,也就是说有多于两个的人想要与他(她)邻座,那么无解。
2.根据要求得出的目标状态为多于一个的环,也无解。
0
回复 东邪歪刀发表于2006-07-28 17:27
提交了若干次……残念……
0
回复 sugar发表于2006-07-28 16:26
这题比赛时真有人ac?
真不好想
为什么得开longint啊?
0
回复 晶星发表于2006-07-25 13:29
排列本质不同的只有二种 正着和反着的
检验几个人不在位置上用数学方法:)模拟法超时的
0
回复 tzkq发表于2006-07-23 04:37
注意别误解题意 b1,b2....bm并不指连续位置上的数
0
回复 Coldwings发表于2006-01-26 09:21
可以用群论证明:如果有k个人不在自己的位置上,那么要且仅要k的代价,即可使这些人归位
剩下的..很简单了吧...
0
回复 lemon_cn发表于2008-08-08 15:55
热烈庆祝用pascal AC的第二题~
p.s.我是C++的~~0
回复 yingjiangyu发表于2015-02-15 21:55
打‘Wrong!’有50分。。0
回复 东大微雕发表于2015-02-07 15:20
这道题真是太好了。奇妙无穷。
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
int a[50005];
int size;
void go(){
int i, j;
int ans = 0;
int dis[50005];
memset(dis, 0, sizeof(dis));
for (i = 1; i <= size; i++){
int d = (a[i] - i + size) % size;
dis[d]++;
}
for (i = 0; i < size; i++){
if (ans < dis[i])
ans = dis[i];
}
memset(dis, 0, sizeof(dis));
for (i = 1; i <= size; i++){
int d = (a[size+1-i]-i+size) % size;
dis[d]++;
}
for (i = 0; i < size; i++){
if (ans < dis[i])ans = dis[i];
}
cout << size-ans << endl;
}
int main(){
freopen("in.txt", "r", stdin);
int neibor[50005][2];
int i;
cin >> size;
for (i = 1; i <= size; i++){
scanf("%d%d",&neibor[i][0],& neibor[i][1]);
}
bool used[50005];
memset(used, 0, sizeof(used));
a[1] = 1;
used[1] = true;
for (i = 2; i <= size; i++){
int last = a[i - 1];
if (!used[neibor[last][0]]){
a[i] = neibor[last][0];
used[a[i]] = true;
}
else if (!used[neibor[last][1]]){
a[i] = neibor[last][1];
used[a[i]] = true;
}
else {
cout << -1 << endl;
return 0;
}
}
if (neibor[1][0] != a[size] && neibor[1][1] != a[size]){
cout << -1 << endl;
return 0;
}
go();
return 0;
}0
回复 3516发表于2014-07-30 08:59
include<stdio.h>include<string.h>
int data[50001][2],shi[50001],a[50001];
int main()
{
int n,i,j,qian,hou; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d%d",&data[i][0],&data[i][1]); } a[1]=1;shi[a[1]]=1 for(i=2;i<=n;i++) { qian=data[a[i-1]][0]; hou=data[a[i-1]][1]; if(shi[qian]==0) { a[i]=qian; shi[qian]=1; } else if(shi[hou]==0) { a[i]=hou; shi[hou]=1; } else { printf("-1"); return 0; } } int temp=0,max=0; memset(shi,0,sizeof(shi)); for(i=1;i<=n;i++) { temp=(n+a[i]-i+1)%n; shi[temp]++; } for(i=0;i<n;i++) { if(max<shi[i]) { max=shi[i]; } } memset(shi,0,sizeof(shi)); for(i=1;i<=n;i++) { temp=(n+a[n-i+1]-i+1)%n; shi[temp]++;
}
for(i=0;i<n;i++)
{
if(max<shi[i])max=shi[i];
}
printf("%d",n-max);
}0
回复 S.Y.F发表于2013-08-31 14:04
题解
1111111129回复于2014-08-13 11:52
orzorzorz0
回复 S.Y.F发表于2013-07-29 16:55
从10、到30、到100。。。。。。
题解:http://blog.163.com/syf_light_feather/blog/static/223755067201362945326756/0
回复 vcvycy发表于2013-06-30 00:56
20 30 40 50 70 分都有~泪流满面.
Accepted100
772 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:55:05
Wrong Answer70
613 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:53:24
Wrong Answer70
686 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:45:35
Wrong Answer70
856 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:42:12
Wrong Answer70
803 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:37:26
Wrong Answer70
882 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:22:39
Wrong Answer70
1145 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:20:30
Wrong Answer10
733 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:11:30
Wrong Answer50
723 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:04:20
Wrong Answer50
781 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:55:49
Wrong Answer40
656 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:49:49
Wrong Answer40
758 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:44:00
Time Exceeded30
7160 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:38:22
Time Exceeded20
7135 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:35:080
回复 SEX丶Elope发表于2013-02-16 10:10
点击查看程序源码+详细题解
cuichen回复于2014-09-09 09:24
怎么又是你??你有什么企图?骗访问量???垃圾!0
回复 qyjubriskxp发表于2010-07-09 21:31
再一次体会到c++流的悲剧,秒杀和3s原来只是输入方式的不同,杯具~~
yuyilahanbao回复于2014-01-24 11:47
从c转到c++第一次不AC(除去忘记把语言有c改为c++的)就是因为c++输入输出的问题
从那次起,我的c++的输入都是用scanf和printf了
因为
保险
安全
我记不清cin是<<还是>>
printf和scanf相对更灵活
....0
回复 slm发表于2010-03-16 18:27
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
嘿嘿0
回复 superyoi发表于2009-11-10 11:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
superyoi killed p1008 with a headshot by awp
0
回复 200853349发表于2009-11-10 10:49
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
当我看到众位神牛打出“置换群”三个字后,我在黑书百度GOOGLE维基百科逛了得有一个半小时多然后回来AC了。。。
思路和strini神牛的基本一样。
0
回复 sinb发表于2009-11-09 13:02
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
其实很简单,不要想复杂了,先是想办法构成,然后用置换群的方法即可ac。0
回复 香蕉派发表于2009-11-06 11:29
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
虽然不懂什么叫置换群,但是思路还是很清晰的。。0
回复 赏金神侠PPF发表于2009-11-05 11:45
一星星纪念~0
回复 strini发表于2009-10-30 22:11
根据群论原理,任何置换群都可以分解为若干个循环节。显然,这道题目就是冲着这点来的。因为如果某循环的长度为L,那么本题中只需要代价为L的操作。注意,这里的L!=1,这是因为只有一个人的循环节不需要任何代价的操作。到这里才只能拿三十分,因为圈是可以旋转的,常规方法需要O(n^2)才能解决。不妨这里以编号为1的人为基准,定义每个人到自己应该所在位置的距离。距离不超过n-1。可以通过最大值来寻找能在自己位置上的最多的人数(因为距离为x的人在旋转x次后转到自己的位置上),那么在比较好的情况下,可以优化到O(n)。TIME: 1H
SUBMIT:
1 70 Error: 发现希望相邻是不精确的,于是改了个搜索方向。(以为题目给定的是按照左右方向,白书说过不能“假定”!)。
2 90 Error: 终于明白要取两个搜索方向的最大值。
3 Accepted.
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 skykey发表于2009-10-29 17:58
#include<iostream>
using namespace std;
int n;
int a[50001],b[50001],c[50001];
int aim[50001];
void G_MAP()
{
bool mark[50001]={false};
int p=1,r=1;
while(p<=n)
{
aim[p]=r;mark[r]=true;p++;
if(!mark[a[r]])r=a[r];
else if(!mark[b[r]])r=b[r];
else if(p<=n){cout<<-1;exit(0);}
}
}
int COMPULATE()
{
int max=0;
int t;
int record[2][50001];
for(int i=1;i<=n;i++)record[0][i]=record[1][i]=0;
for(int i=1;i<=n;i++)
{
if((t=aim[i]-i)<0)t+=n;
record[0][t]++;
if(record[0][t]>max)max=record[0][t];
if((t=aim[i]-(n+1-i))<0)t+=n;
record[1][t]++;
if (record[1][t]>max)max=record[1][t];
}
return max;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{scanf("%d%d",&a[i],&b[i]);c[a[i]]++;c[b[i]]++;}
for(int i=1;i<=n;i++)if(c[i]!=2){cout<<-1;return 0;}G_MAP();
int T=COMPULATE();
cout<<n-T;
}0
回复 song19931218发表于2009-10-27 20:11
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
考虑两种情形(貌似这两种情形很像,但又真的不同,后来才想起,在化学的手性碳原子那部分遇到过类似情况。。。)
然后就是运用置换群的知识0
回复 Aries_C发表于2009-10-25 08:24
正反两遍...两遍...<幽幽的声音飘远..>不然就是70分啊...
不看题解的情况下竟然自己想到了...
记得以前老师给我们做过这题的..细节什么的现在做又忘记了..唉..
0
回复 国防安全员001发表于2009-10-21 22:00
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1701人
提交 4835次
通过率 35%
难度 3题目表述有问题。。
0
回复 liubosen发表于2009-10-21 21:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
yaaaayyayayyayayayayayayayayayayayayayayayyaayayayayayayyaayayayay
var
n,max,i:longint;
a,b,c,d:array[0..50001] of longint;
begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
c[1]:=1;
c[2]:=a[1];
for i:=3 to n do
if c=a[c] then c[i]:=b[c]
else
if c=b[c] then c[i]:=a[c]
else begin
writeln(-1);
halt
end;
if c[n]<>b[1] then
begin
writeln(-1);
halt
end;
fillchar(d,sizeof(d),0);
for i:=1 to n do
inc(d[(c[i]-i+n)mod n]);
for i:=0 to n-1 do
if d[i]>max then max:=d[i];
fillchar(d,sizeof(d),0);
for i:=1 to n do
inc(d[(c[i]+i-1)mod n]);
for i:=0 to n-1 do
if d[i]>max then max:=d[i];
writeln(n-max);
end.0
回复 lishunzhi发表于2009-10-21 00:11
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
置换群,但建环是重点0
回复 zebra发表于2009-10-03 09:48
#include <iostream>
#include <cassert>
using namespace std;
long N,seq[50001],p=1;
class
{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2)
{
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2)
return true;
return false;
}
public:
bool AddE(long v1,long v2)
{
if(isnbr(v1,v2))
return true;
else
if(nbr[v1][0]==2||nbr[v2][0]==2)
return false;
else
{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i)
{
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++)
{
if(!flag[nbr[i][j]])
{
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve()
{
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N;
b=seq[i]-(N+1-i);
if(b<0) b+=N;
if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main()
{
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++)
{
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2))
{
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
system("pause");
return 0;
}0
回复 -117-Join发表于2009-09-18 21:29
哪位大牛帮忙看看我错哪里了
它只得90分
program fire;
type
arr=record
l,r:longint;
end;
var
num:array[1..50000]of longint;
a:array[1..50000]of arr;
b:array[1..50000]of longint;
i,k,j,n:longint;
begin
readln(n);
for i:=1 to n do
readln(a[i].l,a[i].r);
b[1]:=1;
b[n]:=a[1].l;
if a[b[n]].l=b[1]then b[n-1]:=a[b[n]].r
else b[n-1]:=a[b[n]].l;
i:=n-1;
b[2]:=a[1].r;
j:=2;
while j<=i do
begin
if b<>a[b[i]].l then b:=a[b[i]].l
else b:=a[b[i]].r;
dec(i);
if b[j-1]<>a[b[j]].r then b[j+1]:=a[b[j]].r
else b[j+1]:=a[b[j]].l;
inc(j);
end;
for i:=2 to n-1 do
if(b<>a[b[i]].r)and(b<>a[b[i]].l)or(b<>a[b[i]].r)and(b<>a[b[i]].l)then
begin
write(-1);
halt
end;
if(b[n]<>a[b[1]].l)and(b[n]<>a[b[1]].r)or(b[2]<>a[b[1]].l)and(b[2]<>a[b[1]].r)or(b[1]<>a[b[n]].l)and(b[1]<>a[b[n]].r)or(b[n-1]<>a[b[n]].l)and(b[n-1]<>a[b[n]].r)then
begin
write(-1);
halt
end;
num[0]:=0;
for i:=1 to n do
begin
a[b[i]].l:=i;
num[i]:=0;
end;
for i:=1 to n do
if a[i].l-i>=0 then inc(num[a[i].l-i])
else inc(num[a[i].l-i+n]);
j:=0;
for i:=0 to n do
if num[i]>j then j:=num[i];
write(n-j);
end.
写的有点长0
回复 fs302发表于2009-09-17 20:13
分析:学一个好思想:正难则反!由顺序到乱序我们很难快速找到,但是我们知道如何从乱序变为顺序!解决本题利用了组合数学中置换群的思想。从第一个人处断开,将圆环的问题转化为序列的问题。如果可以,求出目标序列。求出目标序列复杂度O(n).
求出目标序列右移0至n-1位置时,不需要移动的人数。将目标序列反转,再求出目标序列右移0至n-1位置时,不需要移动的人数。求不需要移动的人数最大等价于求需要移动的人数最小。复杂度O(n)。
更详细的说:
引进“相对有序”这个概念,当两个人满足C[j]-C[i]==j-i时,两个相对有序。
题目要求最小的总代价,但是我们可以考虑倒过来想,要求最小的总代价亦即求最多有多少人不用移动,亦即相对有序。
然后我们引进一个辅助变量T=C-I,{C-I>=0},T=C[i]-I+N,{C[i]-I<0},那么这个T[i]有什么意义呢?我们知道初始状态的编号是1-N,而目标状态是C[1]-C[N],那么C-I便是从目标状态到初始状态顺时针所要移动的距离,那么如果那么T值相等的两个同学则是相对有序的,亦即不用移动,我们只要找出最大的T然后N-Max(T)就是得到的结果,但是这样还不够,因为刚刚那样只是顺时针所要移动的距离,我们还要计算逆时针的到的结果,从顺时针和逆时针中找到最大的T,然后N-Max(T)才能够是正确结果.0
回复 maxint64发表于2009-09-01 21:33
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
先是物理大发了——以为 b1,b2...bm是连续的
看了牛们的题解 一次ac :)0
回复 柔情使者发表于2009-08-20 15:44
第一遍做的时候没有看题解,自己测了好几遍总是60分,看了n多大牛的解释才恍然大悟,竟然要正反两遍!!!唉,幸亏咱有测试数据,否则我可就惨了...
O(n)的求目标队列算法,都说是冒泡排序,我没看出来,倒是有点像。0
回复 maxiem发表于2009-08-18 20:55
物理自重啊,嘿嘿。
注意要正反两遍哦~
9MS?
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 9ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:9ms
(好像那个冒泡是口胡,大家不要被那个蒙了
program fire;
var
st:array [1..50000,1..2] of longint;
k,final:array [0..50000] of longint;
ex:array [1..50000] of boolean;
p,max,i,n:longint;
begin
fillchar (st,sizeof(st),0);
fillchar (ex,sizeof(ex),0);
fillchar (final,sizeof(final),0);
fillchar (k,sizeof(k),0);
readln (n);
for i:=1 to n do readln (st,st);
final[1]:=1;p:=2;ex[1]:=true;
for i:=1 to n do begin
if ex[st[final[i],1]]=false then begin
final[p]:=st[final[i],1];
ex[st[final[i],1]]:=true;
inc(p);
end
else if ex[st[final[i],2]]=false then begin
final[p]:=st[final[i],2];
ex[st[final[i],2]]:=true;
inc(p);
end;
end;
if p-1<>n then begin
writeln (-1);
halt;
end;
max:=0;
for i:=1 to n do if final[i]>=i then inc(k[final[i]-i]) else inc(k[n-i+final[i]]);
for i:=0 to n-1 do if k[i]>max then max:=k[i];
fillchar (k,sizeof(k),0);
for i:=n downto 1 do if final[i]>=n-i+1 then inc(k[final[i]-n+i-1]) else inc(k[final[i]+i-1]);
for i:=0 to n -1 do if k[i]>max then max:=k[i];
writeln (n-max);
end.0
回复 suning发表于2009-08-14 09:43
啊呜~
一年前误解了题意~
一年后理解了题意~
然后就是1次美妙的ACPS:[误]解[理]解~~~[物理]?
0
回复 fengwuliu发表于2009-08-13 17:20
lgxcgd说的太对了!太感谢了55550
回复 Matt发表于2009-08-11 22:28
NOIP也会考高等数学...由于原图是环,所以置换群可表示为一次循环。作差是个好方法。
但求冒泡排序是怎么作的
0
回复 3830372发表于2009-08-11 21:28
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1504人
提交 4282次
通过率 35%
难度 3提交 讨论 题解 状态
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 尖端才子发表于2009-08-11 11:14
纪念一下……第1500个AC……Flag Accepted
题号 P1008
类型(?) 模拟
通过 1500人
提交 4274次
通过率 35%
难度 3编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 SecretAgent发表于2009-08-10 14:02
置换群是正解编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 yangbei发表于2009-08-07 14:57
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 338ms
├ 测试数据 05:答案正确... 322ms
├ 测试数据 06:答案正确... 306ms
├ 测试数据 07:答案正确... 338ms
├ 测试数据 08:答案正确... 338ms
├ 测试数据 09:答案正确... 322ms├ 测试数据 10:答案正确... 306ms
Accepted 有效得分:100 有效耗时:2270ms
算镜像时偷了点懒,不过也算一遍AC了
0
回复 ja_son发表于2009-08-06 15:44
a:拆环成队,寻求目标队列。
b:b1,b2...bm不是连续的,而且是任意的。只要有成立目标队列,与原来的队列相匹配就可以知道有多少(设为n个)需要移动位置,则代价就是n。
c:目标队列有多种情况,可以反转,也可以左右移动。0
回复 1s发表于2009-08-03 17:56
如对本题有疑问可以参看我的题解:
http://xujieqi.blog.hexun.com/35722312_d.html0
回复 DMKaplony发表于2009-07-30 15:15
当时的时间限制好像是2s。。有个题解说把1定为第一项然后进行冒泡排序。。不过这里是1s 啊。。。也行只有置换群了吧。0
回复 xusc_2009发表于2009-07-28 14:30
看不懂,只好搁浅
什么时候想清楚了再做0
回复 董发表于2009-07-24 19:11
program p1008;
var i,n,k,j,sum1,sum2,ans,max:longint;
a,b,w,d,c:array[0..50005] of longint;begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
w[1]:=1; w[2]:=a[w[1]];
k:=1;repeat
inc(k);
if w[k-1]=a[w[k]] then w[k+1]:=b[w[k]]
else if w[k-1]=b[w[k]] then w[k+1]:=a[w[k]]
else begin
writeln(-1);
exit;
end;
until k=n;
if w[n+1]<>w[1] then
begin
writeln(-1);
exit;
end;for i:=1 to n do
begin
a[i]:=w[i]-i;
b[i]:=w[n-i+1]-i;
if a[i]<0 then a[i]:=a[i]+n;
if b[i]<0 then b[i]:=b[i]+n;
inc(c[a[i]]);
inc(d[b[i]]);
end;
for i:=0 to n-1 do
begin
if ans<c[i] then ans:=c[i];
if ans<d[i] then ans:=d[i];
end;
writeln(n-ans);
end.0
回复 我飞发表于2009-07-23 21:00
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 93狒狒发表于2009-07-23 20:59
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
秒杀......
0
回复 fjxmlhx发表于2009-07-22 13:15
置换群,做2n次,顺时针和逆时针.
对于一个置换,最小操作费用是所有循环长度的和.因此实际上是找出2n个置换中哪个置换循环长度为1的数量最多.0
回复 340508965发表于2009-07-21 15:01
⊙﹏⊙b汗
不知道的以为这是数学竞赛......
...
我的数论与图论可以说脑袋里空白一片.........
怎么办,我的竞赛啊
........算了 看了题解 大家写的
总算弄懂这道题了
先前以为b1,b2,b3..bm是连续的
没想到是任意的!!!!!!!!!诶 叹悲歌未切 为撼奈何编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
总算AC了
program p1008;
var i,n,k,j,sum1,sum2,ans,max:longint;
a,b,w,d,c:array[0..50005] of longint;begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
w[1]:=1; w[2]:=a[w[1]];
k:=1;repeat
inc(k);
if w[k-1]=a[w[k]] then w[k+1]:=b[w[k]]
else if w[k-1]=b[w[k]] then w[k+1]:=a[w[k]]
else begin
writeln(-1);
exit;
end;
until k=n;
if w[n+1]<>w[1] then
begin
writeln(-1);
exit;
end;for i:=1 to n do
begin
a[i]:=w[i]-i;
b[i]:=w[n-i+1]-i;
if a[i]<0 then a[i]:=a[i]+n;
if b[i]<0 then b[i]:=b[i]+n;
inc(c[a[i]]);
inc(d[b[i]]);
end;
for i:=0 to n-1 do
begin
if ans<c[i] then ans:=c[i];
if ans<d[i] then ans:=d[i];
end;
writeln(n-ans);
end.0
回复 zsy90943发表于2009-07-18 00:51
构造巧妙、、看来还是要学好数论和图论额、、、、0
回复 POM无敌牛B发表于2009-07-16 11:47
编译通过...
├ 测试数据 01:运行超时...
├ 测试数据 02:运行超时...
├ 测试数据 03:运行超时...
├ 测试数据 04:运行超时...
├ 测试数据 05:运行超时...
├ 测试数据 06:运行超时...
├ 测试数据 07:运行超时...
├ 测试数据 08:运行超时...
├ 测试数据 09:运行超时...├ 测试数据 10:运行超时...
Unaccepted 有效得分:0 有效耗时:0ms
无奈 哪位哥哥救救我0
回复 yxy发表于2009-06-16 18:16
把置换解释成度为2图,真有才.
求出序列,正反分别做一次差就行了.0
回复 sxpeter发表于2009-06-14 16:56
讲建环吧。数组w表示环,我用的是一种类似并查集的方法。
begin
read(n);
for i:=1 to n do read(a[i],b[i]);
t:=2;w[1]:=1;w[2]:=a[1];
while true do begin
if a[w[t]]<>w[t-1]then w[t+1]:=a[w[t]]//是否在左边
else if b[w[t]]<>w[t-1]then w[t+1]:=b[w[t]]//是否在右边
else begin writeln(-1);halt;end;//失败判断
inc(t);
if t>n then break;
end;
if w[n+1]<>w[1]then begin writeln(-1);halt;end;//本句一定要加!!!!!!
end.0
回复 lgxcgd发表于2009-05-17 20:24
首先把这个圈看做一个图,每个同学看做一个顶点。因为要形成环,所以每个顶点的度必须为2。如果存在度数不为2的顶点,那么整个图无法构成一个环,即“无论怎么调整都不能符合每个同学的愿望”输出-1。
如果是一个环,那么就遍历图,生成以第1个顶点为开头的序列。现在就要求出最小移动的代价。
在理解题意所述的调整方式中,要注意实际上就是把M个在错误位置上的人移动到正确的位置上,代价为M。一次下令移动即可。
假如生成的目标序列为1,5,3,2,4。我们现在就需要比较它和初始状态1,2,3,4,5,看有几个人离开了原来的位置。但这个序列实际代表的是一个环,而且方向正反有两种,就需要把初始序列正反分别转N次,和得到的序列比较,看其中最少有几个位置上的人编号不相同,就得到了我们要求的最小代价。
上述方法有大量冗余。但可以发现转来转去不管怎么转,任意两个人之间的相对位置关系在这过程中都不会变。于是想到做差,如果差小于0则加上N。
1 5 3 2 4
- 1 2 3 4 5
0 3 0 3 4
这表示序列1,5,3,2,4不转动时1,3两个人在原来的位置上,转动3个位置后5和2两个人在原来的位置上,转动4个位置后只有4一个人会在原来的位置上。这就是说,1,5,3,2,4与1,2,3,4,5在旋转后最多有2个位置上的人编号相同,即最少有3个位置上的人编号不相同。同理要反转再求一次。记录每个不同的差值的个数,取其最大值P,即不调换次数最大的。结果N-P就是调换次数最小的。
0
回复 src250发表于2009-05-14 08:27
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
切记:重新构图时一定要对数组清空!我的第一次只有50分,就是这个原因!
0
回复 love19960108发表于2009-04-26 17:59
这题可以用C++这样做么??
#include <iostream>
#include <cassert>
using namespace std;
long N,seq[50001],p=1;
class{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2){
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2) return true;
return false;
}
public:
bool AddE(long v1,long v2){
if(isnbr(v1,v2)) return true;
else if(nbr[v1][0]==2||nbr[v2][0]==2) return false;
else{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i){
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++){
if(!flag[nbr[i][j]]){
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve(){
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N;
b=seq[i]-(N+1-i);
if(b<0) b+=N;
if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main(){
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++){
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2)){
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
return 0;
}0
回复 voyagec2发表于2009-03-18 15:53
难理解,不过算法很精妙0
回复 pRoevollove发表于2009-02-25 23:49
天,把(p[i]-i+n)mod n理所当然地打成了abs(p[i]-i)
结果一直50分……还一直以为自己构造错了……ps 我可以过楼下的范例哦
0
回复 ufo172849z发表于2009-01-24 23:05
ms楼下的程序不能处理这种反例(测试数据还是不够强啊)
6
2 3
1 3
1 2
5 6
4 6
4 5
应该输出-1的吧?因为是两个环var a,b:array[0..50000]of longint;
c:array[0..50000,1..2]of longint;
d:array[0..50000]of boolean;
i,j,k,m,n,max:longint;
can:boolean;begin
readln(n);
for i:=1 to n do
readln(c,c);
b[0]:=c[1,1]; b[n]:=c[1,1];
fillchar(d,sizeof(d),0);
k:=1;
can:=true;
for i:=1 to n-1 do
begin
if d[k] then can:=false;
b[i]:=k; d[k]:=true;
if b=c[k,1] then k:=c[k,2]
else if b=c[k,2] then k:=c[k,1]
else can:=false;
if not can then break;
end;
if can then
if b[n]<>k then can:=false;
if can then
begin
max:=-1;
fillchar(a,sizeof(a),0);
for i:=1 to n do
inc(a[(b[i]-i+n) mod n]);
for i:=0 to n-1 do
if a[i]>max then max:=a[i];
fillchar(a,sizeof(a),0);
for i:=1 to n do
inc(a[(b[n-i+1]-i+n)mod n]);
for i:=1 to n-1 do
if a[i]>max then max:=a[i];
writeln(n-max);
end
else
writeln(-1);
end.0
回复 tangdongjian发表于2009-01-23 22:17
我在做镜像时把原先max直接覆盖上了,注意0
回复 永恒888发表于2009-10-26 22:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 tangkunjie发表于2009-06-04 19:50
挺烦人的题目0
回复 ykspeter发表于2008-11-13 20:32
program fire(input,output);
var
n,i,j,k,max,v:longint;
a:array[0..100000,1..2] of longint;
b,c:array[0..100000] of longint;
begin
readln(n);
for i:=1 to n do readln(a,a);
for i:=1 to n do
begin
k:=0;
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if (k=4) or (k=3)
then begin
writeln('-1');
exit
end
end;
b[1]:=1;i:=2;k:=a[1,1];j:=1;
repeat
b[i]:=k;
inc(i);
v:=k;
if a[k,1]<>j
then k:=a[k,1]
else k:=a[k,2];
j:=v;
until i=n+1;
fillchar(c,sizeof(c),0);
for i:=1 to n do inc(c[(b[i]-i+n)mod n]);
for i:=0 to n-1 do
if c[i]>max
then max:=c[i];
fillchar(c,sizeof(c),0);max:=0;
for i:=1 to n do inc(c[(b[n-i+1]-i+n)mod n]);
for i:=n-1 downto 0 do
if c[i]>max
then max:=c[i];
writeln(n-max);
end.0
回复 getuojian发表于2008-11-10 13:38
#include<stdio.h>
#include<memory.h>const int maxn=50010;
int n;
int f[maxn][2];
int goal[maxn];
int ans=maxn;
int hash[maxn];bool SET_ORI(){
bool flag[maxn];
memset(flag, true, sizeof(flag));
goal[1]=1; flag[1]=false;
for (int i=1; i<=n-1; i++){
if (flag[f[goal[i]][0]]){
goal=f[goal[i]][0];
flag[f[goal[i]][0]]=false;
continue;
}
if (flag[f[goal[i]][1]]){
goal=f[goal[i]][1];
flag[f[goal[i]][1]]=false;
continue;
}
return false;
}
if ((goal[n]!=f[1][0]) && (goal[n]!=f[1][1]))
return false;
return true;
}
int SWAP(int i, int j){
int t=goal[i];
goal[i]=goal[j];
goal[j]=t;
return 0;
}int min(int i, int j){
return i>j?j:i;
}
int HASH(){
for(int i=1; i<=n; i++)
hash[i]=goal[i]-i+n;
return 0;
}int CALC(){
int temp[maxn*2], back=0;
memset(temp, 0, sizeof(temp));
for (int i=1; i<=n; i++)
temp[hash[i]%n]++;
for (int i=1; i<=2*n-1; i++)
if (temp[i] > back)
back=temp[i];
return back;
}int main(){
freopen("fire.in", "r", stdin);
freopen("fire.out", "w", stdout);
scanf("%d", &n);
for (int i=1; i<=n; i++)
scanf("%d %d", &f[i][0], &f[i][1]);
if (!SET_ORI()){
printf("-1");
return 0;
}
//forward
HASH();
ans=min(ans, n-CALC());
//backward
for (int i=1; i<=n/2; i++)
SWAP(i,n-i+1);
HASH();
ans=min(ans, n-CALC());printf("%d", ans);
return 0;
}0
回复 IVORY发表于2008-11-06 10:46
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
CHEAT的...
0
回复 storey p发表于2008-11-05 14:19
回447389831:
exit换成halt0
回复 FenXy发表于2008-11-04 08:28
艺术p2450
回复 hlq发表于2008-11-01 14:31
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms求不在位置上的人数
a【i】 第i位上的同学编号
for i:=1 to n do
begin
inc(b[(a[i]-i+n) mod n])
end;
max:=0;
for i:=0 to n-1 do
if b[i]>max then max:=b[i];
fillchar(b,sizeof(b),0);
for i:=1 to n do
begin
inc(b[(a[i]-(n-i+1)+n)mod n]);//对称
end;
for i:=0 to n-1 do
if b[i]>max then max:=b[i];0
回复 Will~骷髅发表于2008-10-30 21:37
编译通过...
├ 测试数据 01:运行超时...
├ 测试数据 02:运行超时...
├ 测试数据 03:运行时错误...|错误号: -1073741819
├ 测试数据 04:运行时错误...|错误号: -1073741819
├ 测试数据 05:运行时错误...|错误号: -1073741819
├ 测试数据 06:运行时错误...|错误号: -1073741819
├ 测试数据 07:运行时错误...|错误号: -1073741819
├ 测试数据 08:运行时错误...|错误号: -1073741819
├ 测试数据 09:运行时错误...|错误号: -1073741819├ 测试数据 10:运行时错误...|错误号: -1073741819
Unaccepted 有效得分:0 有效耗时:0ms
怎么会这样???
0
回复 悲伤逆流成河发表于2008-10-28 22:13
#include <iostream>
#include <fstream>
using namespace std ;int hash[50001];
int n , i , j , t , maxs(0) ;inline void HASH ( int e[] )
{
for ( i = 1 ; i <= n ; i++ )
{
e[i] -= i ;
if ( e[i] < 0 ) e[i] += n ;
hash[e[i]]++ ;
}
for ( i = 0 ; i < 50001 ; i++ )
if ( maxs < hash[i] ) maxs = hash[i] ;
}int main(){
ifstream fin ("fire.in") ;
ofstream fout ("fire.out") ;fin >> n ;
int e[n+1] , h[n+1][2] , e2[n+1];
bool f[n+1] ;
for ( i = 1 ; i <= n ; i++ )
{
f[i] = false ;
fin >> h[i][0] >> h[i][1] ;
}
e[1] = 1 ;
f[1] = true ;
for ( i = 2 ; i <= n ; i++ )
{
if ( e < 0 ) { fout << -1 << endl ; exit(0) ; }
if ( !f [ h[ e ][0] ] ) e[i] = h[ e ][0] ;
if ( !f [ h[ e ][1] ] ) e[i] = h[ e ][1] ;
f[ e[i] ] = true ;
}
for ( i = 1 , j = n ; i <= n ; i++,j-- ) e2[j] = e[i] ;
HASH ( e ) ;
memset ( hash , 0 , sizeof ( hash ) ) ;
HASH ( e2 ) ;
fout << n - maxs << endl ;
}0
回复 evelynhe发表于2008-10-26 16:31
“置换群思想...今天刚明白...先构造新数列(要构造两次,否则只有70分),然后向右计算相对位置差,然后累加记录数组,然后用N减去相对位置差累加值最大的,就是答案... ”
这是真的
0
回复 true1023发表于2008-10-25 09:32
置换群的基本概念
利用原序列和目标序列每个元素的绝对位置差来求出原序列每个元素对于目标序列的相对位置,找相对位置相同的最多的元素数,用总元素数减去它即为结果。0
回复 447389831发表于2008-10-21 09:45
program fire(input,output);
var
n,i,j,k,max,v:longint;
a:array[0..100000,1..2] of longint;
b,c:array[0..100000] of longint;
begin
readln(n);
for i:=1 to n do readln(a,a);
for i:=1 to n do
begin
k:=0;
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if (k=4) or (k=3)
then begin
writeln('-1');
exit
end
end;
b[1]:=1;i:=2;k:=a[1,1];j:=1;
repeat
b[i]:=k;
inc(i);
v:=k;
if a[k,1]<>j
then k:=a[k,1]
else k:=a[k,2];
j:=v;
until i=n+1;
fillchar(c,sizeof(c),0);
for i:=1 to n do inc(c[(b[i]-i+n)mod n]);
for i:=0 to n-1 do
if c[i]>max
then max:=c[i];
fillchar(c,sizeof(c),0);max:=0;
for i:=1 to n do inc(c[(b[n-i+1]-i+n)mod n]);
for i:=n-1 downto 0 do
if c[i]>max
then max:=c[i];
writeln(n-max);
end.
90 分,牛人门帮看下把0
回复 cnfnje1发表于2008-10-17 18:12
置换群.....是什么?
readln(n);
for i:=1 to n do readln(a[i],b[i]);
c[1]:=1; c[2]:=a[1];
for i:=3 to n do if c=a[c] then c[i]:=b[c]
else if c=b[c] then c[i]:=a[c]
else begin writeln(-1); halt end;
if c[n]<>b[1] then begin writeln(-1); halt end;
fillchar(d,sizeof(d),0);
for i:=1 to n do inc(d[(c[i]-i+n)mod n]);
for i:=0 to n-1 do if d[i]>m then m:=d[i];
fillchar(d,sizeof(d),0);
for i:=1 to n do inc(d[(c[i]+i-1)mod n]);
for i:=0 to n-1 do if d[i]>m then m:=d[i];
writeln(n-m);
是么?0
回复 lyrics发表于2008-10-12 19:55
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
技巧性比较强吧,楼下不必构造2次,计算时从头至尾算一次,再倒过来算一次就行了
0
回复 LV.唱响发表于2008-10-05 08:38
置换群思想...今天刚明白...先构造新数列(要构造两次,否则只有70分),然后向右计算相对位置差,然后累加记录数组,然后用N减去相对位置差累加值最大的,就是答案...
0
回复 宇智波带波斯猫发表于2008-10-05 08:33
Flag Accepted
题号 P1008
类型(?) 其它
通过 1065人
提交 3000次
通过率 35%
难度 3第3000个提交的
0
回复 鸳鸯羡发表于2008-09-28 18:19
#include <iostream>
using namespace std ;int hash[50001];
int n , i , j , t , maxs(0) ;inline void HASH ( int e[] )
{
for ( i = 1 ; i <= n ; i++ )
{
e[i] -= i ;
if ( e[i] < 0 ) e[i] += n ;
hash[e[i]]++ ;
}
for ( i = 0 ; i < 50001 ; i++ )
if ( maxs < hash[i] ) maxs = hash[i] ;
}int main(){
cin >> n ;
int e[n+1] , h[n+1][2] , e2[n+1];
bool f[n+1] ;
for ( i = 1 ; i <= n ; i++ )
{
f[i] = false ;
cin >> h[i][0] >> h[i][1] ;
}
e[1] = 1 ;
f[1] = true ;
for ( i = 2 ; i <= n ; i++ )
{
if ( e < 0 ) { cout << -1 << endl ; exit(0) ; }
if ( !f [ h[ e ][0] ] ) e[i] = h[ e ][0] ;
if ( !f [ h[ e ][1] ] ) e[i] = h[ e ][1] ;
f[ e[i] ] = true ;
}
for ( i = 1 , j = n ; i <= n ; i++,j-- ) e2[j] = e[i] ;
HASH ( e ) ;
memset ( hash , 0 , sizeof ( hash ) ) ;
HASH ( e2 ) ;
cout << n - maxs << endl ;
}80分
0
回复 月光疾风发表于2008-09-25 13:03
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
纪念我第200次提交!过第79题。。。。0
回复 ghostplant发表于2008-09-20 19:48
#include <iostream>
#include <fstream>
#include <cassert>
using namespace std;
long N,seq[50001],p=1;
class{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2){
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2) return true;
return false;
}
public:
bool AddE(long v1,long v2){
if(isnbr(v1,v2)) return true;
else if(nbr[v1][0]==2||nbr[v2][0]==2) return false;
else{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i){
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++){
if(!flag[nbr[i][j]]){
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve(void){
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N;
b=seq[i]-(N+1-i);
if(b<0) b+=N;
if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main(){
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++){
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2)){
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
return 0;
}0
回复 zzh19950802发表于2008-09-17 19:29
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案错误... ├ 标准行输出
├ 错误行输出
├ 测试数据 05:答案错误... ├ 标准行输出
├ 错误行输出
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 462ms
├ 测试数据 08:答案正确... 369ms
├ 测试数据 09:答案正确... 384ms
├ 测试数据 10:答案错误...程序输出比正确答案长
为什么我的程序不对?
#include <iostream>
using namespace std;
#define MAXN 50000
int man[MAXN+2][2];
int cercle[MAXN+2]={0,1};
int used[MAXN+2]={0};
int reduce[2][MAXN+2]={0};
int n;
int main()
{
long i,p,q=1,t;
int max=0;
cin>>n;
for (i=1;i<=n;i++) cin>>man[i][0]>>man[i][1];
p=man[q][1];
for (i=2;i<=n+1;i++)
{
if (man[q][1]==p)
{
p=q;
q=man[q][0];
}
else
{
if(man[q][0]!=p) break;
p=q;
q=man[q][1];
}
if(used[q]) break;
else used[q]=1;
cercle[i]=q;
}
if (i<=n+1) cout<<-1;
else
{
for (i=1;i<=n;i++)
{
if((t=cercle[i]-i)<0) t+=n;
reduce[0][t]++;
if (reduce[0][t]>max) max=reduce[0][t];
if ((t=cercle[i]-n+i-1)<0) t+=n;
if (reduce[1][t]>max) max=reduce[1][t];
}
cout<<n-max;
}
return 0;
}0
回复 liaorc发表于2008-09-16 17:56
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 cxy450090074发表于2008-09-04 13:34
oh no0
回复 Lost.G发表于2008-08-22 15:49
我在想``怎么样才能不看错这题呢0
回复 bonism发表于2008-08-14 21:30
时间复杂度O(N)。。。原来我一直把题意理解错。。。囧!!。。
关于“置换群”,请看LRJ的《算法艺术与信息学竞赛》P245那一小节,还是比较好理解的。
0
回复 lemon_cn发表于2008-08-08 15:55
热烈庆祝用pascal AC的第二题~
p.s.我是C++的~~0
回复 oipn4e2发表于2008-08-05 21:36
解决效率不高,但AC了。0
回复 notblack发表于2008-08-01 09:17
用距离来分类,统计在原位的最大人数,奇怪的是
b[1]:=1;
b[2]:=a[1,1];
b[n]:=a[1,2];建环的时候,上面的改成
b[1]:=1;
b[2]:=a[1,2];
b[n]:=a[1,1];最后一个点却过不了,太奇怪了.
0
回复 332404521发表于2008-07-14 13:53
对于初三刚刚中考完的我,要理解这题的意思是万万不能的。。。
看题解我知道了应该怎么做,但那不是我的,所以不做了。。。
哪天能证明出来那啥再来做0
回复 Sheeta发表于2007-11-14 15:45
好简单啊
直接贪啊
(P.S.置换群?什么东东...)0
回复 mingyueyucai发表于2007-11-09 21:22
我代码写了老长老长,结果还是只过了8个点,有没有搞错?
我想请问一下,我和大家的一样,先排列出目标状态.然后确定初始状态时使得最多的人在目标位置上,然后交换.但是得到的答案总是偏大一点.
然后我又把所有可以使最多的人在原位目标位置上的可能都尝试了一编(包括正反两个目标状态),结果还是只能过8个点,有2个点死都过不了!
我的算法有什么问题吗?0
回复 luanjiyang发表于2007-11-08 08:44
很委琐的说 我提交了8遍。。
0→0→10→10→10→10→70→AC- -||
0
回复 lonelycorn发表于2007-11-05 23:31
数论……好底歇的东西。0
回复 gamejifan发表于2007-11-04 11:15
这题的叙述,让我误会了一年多。tzkq……3q..要早知道是这种意思早就ac了这题。。显然没什么大意思,看过组合数学或者学过群论的都懂。。ms跟polya计数法那个循环的意思。。写的时候竟然因为交换的时候写错一个字母wa。我汗。
0
回复 Alexandria发表于2007-11-01 13:33
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
好强大的题啊,不看题解还真不会!
0
回复 clfhaha1234发表于2007-10-30 18:09
请问什么是置换群啊?可以讲讲吗?………………0
回复 rleepas发表于2007-10-30 13:18
楼下都是正解?
......0
回复 Ice_Msk发表于2007-10-18 20:35
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
什么是置换群?不知道。。。照样过。。。。
0
回复 junlonely发表于2007-10-18 20:13
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 江南不才发表于2007-10-11 16:19
排序法这里会超时~~~~~
比赛的时间是2S~~
这里是1S~~
(_)0
回复 秒杀群众发表于2007-10-10 17:05
居然是置换群。。。
对了。。。什么是置换群...
上网查啊!!!0
回复 southstarj1发表于2007-10-02 18:50
思想:
置换群。(相关知识自己查)
对于一组数据,按各人的意愿排出一个序列,
如果无法排出,就输出-1。
再将环状序列变成链状,则这个目标序列为一个置换群,
与原序列(按1到n的一列)满足:
交换的最少人数等于目标序列与原序列不重合的人数。
因为总共有2n个目标序列(正反各n种),都算一遍就行了。步骤:
1. 读入数据;
2. 构造一个目标序列;
3. 统计该序列中元素位置与该元素在原序列位置的差值(同一方向)为i{i ∈ [0, n)}的元素个数;
4. 将该序列的反序统计一遍;
5. 从这些数据中选取一个最大的值max;
6. 输出n - max;注意:
构造目标序列时判断能否构造的条件;
统计一次差值的复杂度是O(n);
统计差值的目的是求与原序列最多的重合人数;0
回复 wangjin5发表于2007-09-19 22:38
好经典的题奥
确实有难度0
回复 the_melody发表于2007-09-03 17:58
Accepted 有效得分:100 有效耗时:0ms
好经典的题奥0
回复 richardxx发表于2007-08-22 17:36
下面程序是错的,不好意思,弄错地方了....0
回复 sm-star发表于2007-08-21 15:18
题目所求就是每次进行连续交换的人数总和,这样,一个看似复杂的题目就变的异常的简单了!0
回复 wasyyyy发表于2007-08-11 02:05
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
HOHO~~~看讨论的时候看到有人提到‘置换群’这个东西,突然想起来我刚买的一本组合数学上有这么一块东西,就拿过来看了。。。。
然后就出现上面的东西了。。。。置换群,本来想求轮换的,发现轮换比较多,还是找不参与交换的比较好记。。。。优化的方法。。。我看了下好象不只一个人讲过了。。。而且似乎我跟他们的都一样(没仔细看)所以就不说了。。。效率是O(n)的。。不用建环。
0
回复 angieqiu发表于2007-08-10 22:49
怎么判断建环失败啊?我的程序虽然AC但总觉得方法很傻0
回复 梦ぁ逍遥发表于2007-07-17 13:45
想到了用t[i]=b[i]-i表示环
却没想到镜像..十分感谢visister
让我从90分中挣扎出来...0
回复 visister发表于2007-06-01 00:12
首先明显地可以知道我们需要对于目标状态建立出一个环。如果无法建立这个环,那么结果一定是-1,当建立好环以后可以知道最小移动代价一定等于最少的不在目标位置上的人数。那么我们可以对目标环进行顺时针旋转1~n-1之中任意一个,答案就一定等于旋转中的不在自己位置上的人数最少的那样的环的状态。但是对于50000的数据,我们如果要将环旋转1~n-1次,那么总共加上判断不在自己位置上的人数时间复杂度为O(n^2),显然在限定时间内是无法出解的。因此我们进行逆向思维:不在自己位置上最少的人数就一定会等于总人数减去在自己位置上最多的人数(仔细想想),那么我们就将该问题转化为了求在自己的位置上最多的人数,这样一来,我们对初始目标环中每一个位置进行判断需要旋转多少次可以回到自己位置上,每一个人的选择都将映射到[0..n-1]的数组中,选取当中最大的情况就为所求,但是考虑到环可以反转,那么我们还需要将环再求一次镜像,就可以得到初始目标需要旋转多少次可以得到在自己位置上最多的人数的环的状态,最后通过总的人数减去它即为问题所求,时间复杂度为O(n);0
回复 pyh119发表于2006-11-16 20:11
哪个人不小心失火了找我啊!!!PS:我是安徽省芜湖市119接线员....
0
回复 maomingming发表于2006-11-06 18:40
考虑旋转后最多可能重合的情况,另要注意圈可以反过来0
回复 qian5发表于2006-09-30 21:35
直接输出‘-1’有一个点过0
回复 BambooLeaf发表于2006-09-26 18:17
见过的最牛最简单的方法……
将此题转换为冒泡排序,记录下所有交换的次数和两数间的距离,加上就行了……—__—|||
具体是这样的,我们反向思维,本来是要求一个有序数列求出成为无序数列的代价,现在我们把无序数列(即目标数列)进行冒泡排序,然后……就是这样……
看完之后,偶巨汗……0
回复 xcjzj发表于2006-09-26 17:18
每组数据确定两组相对位置关系,并且这两组互为镜像。
对于某一种排列方式,不在需要位置上的人数即为当前状态到目标状态的最小代价。
先找出其中一种排列方式。由于目标状态可以通过旋转而使得部分人的变化次数减少,所以找出每个人通过某一固定方向旋转到达目标位置的旋转次数。找到某一次数,使得拥有这个次数的人数最多。那么,通过旋转这一最多人拥有的次数,即可使得尽可能多的人不通过交换直接到达目标位置。于是,不拥有这一旋转次数的人数即为这一状态下的最小代价。
然后,用现在的目标状态找出其镜像状态,并且用上述方法再找一遍最小代价,与前面的结果比较,较小值即为答案。
另外,题目中会出现一些无解的情况:
1.某个人被“要”的次数多于两次,也就是说有多于两个的人想要与他(她)邻座,那么无解。
2.根据要求得出的目标状态为多于一个的环,也无解。0
回复 东邪歪刀发表于2006-07-28 17:27
提交了若干次……残念……0
回复 sugar发表于2006-07-28 16:26
这题比赛时真有人ac?
真不好想
为什么得开longint啊?0
回复 晶星发表于2006-07-25 13:29
排列本质不同的只有二种 正着和反着的
检验几个人不在位置上用数学方法:)模拟法超时的0
回复 tzkq发表于2006-07-23 04:37
注意别误解题意 b1,b2....bm并不指连续位置上的数0
回复 Coldwings发表于2006-01-26 09:21
可以用群论证明:如果有k个人不在自己的位置上,那么要且仅要k的代价,即可使这些人归位剩下的..很简单了吧...
0
回复 cxy450090074发表于2008-09-04 13:34
oh no
没有更多题解了 ╮(╯O╰)╭
UPYUN
评测机们树形图设计者
上海红茶馆
Jtwd2
VijosEx
Vijos 2.0 动态2014-9-25 备案完毕
2014-9-28 更换服务器
2014-11-28 微小更新
2015-7-10 重新开启MC服务
实验室 | API | 博客 | 帮助 | 隐私 | 联系 | 关于 | 沪ICP备14040537号
© Copyright Vijos, cfc0146 beta, in 167.53793 ms -
-12015-07-05 11:02:38@
0
回复 yingjiangyu发表于2015-02-15 21:55
打‘Wrong!’有50分。。0
回复 东大微雕发表于2015-02-07 15:20
这道题真是太好了。奇妙无穷。
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
int a[50005];
int size;
void go(){
int i, j;
int ans = 0;
int dis[50005];
memset(dis, 0, sizeof(dis));
for (i = 1; i <= size; i++){
int d = (a[i] - i + size) % size;
dis[d]++;
}
for (i = 0; i < size; i++){
if (ans < dis[i])
ans = dis[i];
}
memset(dis, 0, sizeof(dis));
for (i = 1; i <= size; i++){
int d = (a[size+1-i]-i+size) % size;
dis[d]++;
}
for (i = 0; i < size; i++){
if (ans < dis[i])ans = dis[i];
}
cout << size-ans << endl;
}
int main(){
freopen("in.txt", "r", stdin);
int neibor[50005][2];
int i;
cin >> size;
for (i = 1; i <= size; i++){
scanf("%d%d",&neibor[i][0],& neibor[i][1]);
}
bool used[50005];
memset(used, 0, sizeof(used));
a[1] = 1;
used[1] = true;
for (i = 2; i <= size; i++){
int last = a[i - 1];
if (!used[neibor[last][0]]){
a[i] = neibor[last][0];
used[a[i]] = true;
}
else if (!used[neibor[last][1]]){
a[i] = neibor[last][1];
used[a[i]] = true;
}
else {
cout << -1 << endl;
return 0;
}
}
if (neibor[1][0] != a[size] && neibor[1][1] != a[size]){
cout << -1 << endl;
return 0;
}
go();
return 0;
}0
回复 3516发表于2014-07-30 08:59
include<stdio.h>include<string.h>
int data[50001][2],shi[50001],a[50001];
int main()
{
int n,i,j,qian,hou; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d%d",&data[i][0],&data[i][1]); } a[1]=1;shi[a[1]]=1 for(i=2;i<=n;i++) { qian=data[a[i-1]][0]; hou=data[a[i-1]][1]; if(shi[qian]==0) { a[i]=qian; shi[qian]=1; } else if(shi[hou]==0) { a[i]=hou; shi[hou]=1; } else { printf("-1"); return 0; } } int temp=0,max=0; memset(shi,0,sizeof(shi)); for(i=1;i<=n;i++) { temp=(n+a[i]-i+1)%n; shi[temp]++; } for(i=0;i<n;i++) { if(max<shi[i]) { max=shi[i]; } } memset(shi,0,sizeof(shi)); for(i=1;i<=n;i++) { temp=(n+a[n-i+1]-i+1)%n; shi[temp]++;
}
for(i=0;i<n;i++)
{
if(max<shi[i])max=shi[i];
}
printf("%d",n-max);
}0
回复 S.Y.F发表于2013-08-31 14:04
题解
1111111129回复于2014-08-13 11:52
orzorzorz0
回复 S.Y.F发表于2013-07-29 16:55
从10、到30、到100。。。。。。
题解:http://blog.163.com/syf_light_feather/blog/static/223755067201362945326756/0
回复 vcvycy发表于2013-06-30 00:56
20 30 40 50 70 分都有~泪流满面.
Accepted100
772 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:55:05
Wrong Answer70
613 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:53:24
Wrong Answer70
686 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:45:35
Wrong Answer70
856 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:42:12
Wrong Answer70
803 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:37:26
Wrong Answer70
882 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:22:39
Wrong Answer70
1145 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:20:30
Wrong Answer10
733 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:11:30
Wrong Answer50
723 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:04:20
Wrong Answer50
781 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:55:49
Wrong Answer40
656 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:49:49
Wrong Answer40
758 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:44:00
Time Exceeded30
7160 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:38:22
Time Exceeded20
7135 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:35:080
回复 SEX丶Elope发表于2013-02-16 10:10
点击查看程序源码+详细题解
cuichen回复于2014-09-09 09:24
怎么又是你??你有什么企图?骗访问量???垃圾!0
回复 qyjubriskxp发表于2010-07-09 21:31
再一次体会到c++流的悲剧,秒杀和3s原来只是输入方式的不同,杯具~~
yuyilahanbao回复于2014-01-24 11:47
从c转到c++第一次不AC(除去忘记把语言有c改为c++的)就是因为c++输入输出的问题
从那次起,我的c++的输入都是用scanf和printf了
因为
保险
安全
我记不清cin是<<还是>>
printf和scanf相对更灵活
....0
回复 slm发表于2010-03-16 18:27
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
嘿嘿0
回复 superyoi发表于2009-11-10 11:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
superyoi killed p1008 with a headshot by awp
0
回复 200853349发表于2009-11-10 10:49
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
当我看到众位神牛打出“置换群”三个字后,我在黑书百度GOOGLE维基百科逛了得有一个半小时多然后回来AC了。。。
思路和strini神牛的基本一样。
0
回复 sinb发表于2009-11-09 13:02
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
其实很简单,不要想复杂了,先是想办法构成,然后用置换群的方法即可ac。0
回复 香蕉派发表于2009-11-06 11:29
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
虽然不懂什么叫置换群,但是思路还是很清晰的。。0
回复 赏金神侠PPF发表于2009-11-05 11:45
一星星纪念~0
回复 strini发表于2009-10-30 22:11
根据群论原理,任何置换群都可以分解为若干个循环节。显然,这道题目就是冲着这点来的。因为如果某循环的长度为L,那么本题中只需要代价为L的操作。注意,这里的L!=1,这是因为只有一个人的循环节不需要任何代价的操作。到这里才只能拿三十分,因为圈是可以旋转的,常规方法需要O(n^2)才能解决。不妨这里以编号为1的人为基准,定义每个人到自己应该所在位置的距离。距离不超过n-1。可以通过最大值来寻找能在自己位置上的最多的人数(因为距离为x的人在旋转x次后转到自己的位置上),那么在比较好的情况下,可以优化到O(n)。TIME: 1H
SUBMIT:
1 70 Error: 发现希望相邻是不精确的,于是改了个搜索方向。(以为题目给定的是按照左右方向,白书说过不能“假定”!)。
2 90 Error: 终于明白要取两个搜索方向的最大值。
3 Accepted.
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 skykey发表于2009-10-29 17:58
#include<iostream>
using namespace std;
int n;
int a[50001],b[50001],c[50001];
int aim[50001];
void G_MAP()
{
bool mark[50001]={false};
int p=1,r=1;
while(p<=n)
{
aim[p]=r;mark[r]=true;p++;
if(!mark[a[r]])r=a[r];
else if(!mark[b[r]])r=b[r];
else if(p<=n){cout<<-1;exit(0);}
}
}
int COMPULATE()
{
int max=0;
int t;
int record[2][50001];
for(int i=1;i<=n;i++)record[0][i]=record[1][i]=0;
for(int i=1;i<=n;i++)
{
if((t=aim[i]-i)<0)t+=n;
record[0][t]++;
if(record[0][t]>max)max=record[0][t];
if((t=aim[i]-(n+1-i))<0)t+=n;
record[1][t]++;
if (record[1][t]>max)max=record[1][t];
}
return max;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{scanf("%d%d",&a[i],&b[i]);c[a[i]]++;c[b[i]]++;}
for(int i=1;i<=n;i++)if(c[i]!=2){cout<<-1;return 0;}G_MAP();
int T=COMPULATE();
cout<<n-T;
}0
回复 song19931218发表于2009-10-27 20:11
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
考虑两种情形(貌似这两种情形很像,但又真的不同,后来才想起,在化学的手性碳原子那部分遇到过类似情况。。。)
然后就是运用置换群的知识0
回复 Aries_C发表于2009-10-25 08:24
正反两遍...两遍...<幽幽的声音飘远..>不然就是70分啊...
不看题解的情况下竟然自己想到了...
记得以前老师给我们做过这题的..细节什么的现在做又忘记了..唉..
0
回复 国防安全员001发表于2009-10-21 22:00
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1701人
提交 4835次
通过率 35%
难度 3题目表述有问题。。
0
回复 liubosen发表于2009-10-21 21:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
yaaaayyayayyayayayayayayayayayayayayayayayyaayayayayayayyaayayayay
var
n,max,i:longint;
a,b,c,d:array[0..50001] of longint;
begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
c[1]:=1;
c[2]:=a[1];
for i:=3 to n do
if c=a[c] then c[i]:=b[c]
else
if c=b[c] then c[i]:=a[c]
else begin
writeln(-1);
halt
end;
if c[n]<>b[1] then
begin
writeln(-1);
halt
end;
fillchar(d,sizeof(d),0);
for i:=1 to n do
inc(d[(c[i]-i+n)mod n]);
for i:=0 to n-1 do
if d[i]>max then max:=d[i];
fillchar(d,sizeof(d),0);
for i:=1 to n do
inc(d[(c[i]+i-1)mod n]);
for i:=0 to n-1 do
if d[i]>max then max:=d[i];
writeln(n-max);
end.0
回复 lishunzhi发表于2009-10-21 00:11
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
置换群,但建环是重点0
回复 zebra发表于2009-10-03 09:48
#include <iostream>
#include <cassert>
using namespace std;
long N,seq[50001],p=1;
class
{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2)
{
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2)
return true;
return false;
}
public:
bool AddE(long v1,long v2)
{
if(isnbr(v1,v2))
return true;
else
if(nbr[v1][0]==2||nbr[v2][0]==2)
return false;
else
{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i)
{
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++)
{
if(!flag[nbr[i][j]])
{
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve()
{
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N;
b=seq[i]-(N+1-i);
if(b<0) b+=N;
if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main()
{
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++)
{
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2))
{
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
system("pause");
return 0;
}0
回复 -117-Join发表于2009-09-18 21:29
哪位大牛帮忙看看我错哪里了
它只得90分
program fire;
type
arr=record
l,r:longint;
end;
var
num:array[1..50000]of longint;
a:array[1..50000]of arr;
b:array[1..50000]of longint;
i,k,j,n:longint;
begin
readln(n);
for i:=1 to n do
readln(a[i].l,a[i].r);
b[1]:=1;
b[n]:=a[1].l;
if a[b[n]].l=b[1]then b[n-1]:=a[b[n]].r
else b[n-1]:=a[b[n]].l;
i:=n-1;
b[2]:=a[1].r;
j:=2;
while j<=i do
begin
if b<>a[b[i]].l then b:=a[b[i]].l
else b:=a[b[i]].r;
dec(i);
if b[j-1]<>a[b[j]].r then b[j+1]:=a[b[j]].r
else b[j+1]:=a[b[j]].l;
inc(j);
end;
for i:=2 to n-1 do
if(b<>a[b[i]].r)and(b<>a[b[i]].l)or(b<>a[b[i]].r)and(b<>a[b[i]].l)then
begin
write(-1);
halt
end;
if(b[n]<>a[b[1]].l)and(b[n]<>a[b[1]].r)or(b[2]<>a[b[1]].l)and(b[2]<>a[b[1]].r)or(b[1]<>a[b[n]].l)and(b[1]<>a[b[n]].r)or(b[n-1]<>a[b[n]].l)and(b[n-1]<>a[b[n]].r)then
begin
write(-1);
halt
end;
num[0]:=0;
for i:=1 to n do
begin
a[b[i]].l:=i;
num[i]:=0;
end;
for i:=1 to n do
if a[i].l-i>=0 then inc(num[a[i].l-i])
else inc(num[a[i].l-i+n]);
j:=0;
for i:=0 to n do
if num[i]>j then j:=num[i];
write(n-j);
end.
写的有点长0
回复 fs302发表于2009-09-17 20:13
分析:学一个好思想:正难则反!由顺序到乱序我们很难快速找到,但是我们知道如何从乱序变为顺序!解决本题利用了组合数学中置换群的思想。从第一个人处断开,将圆环的问题转化为序列的问题。如果可以,求出目标序列。求出目标序列复杂度O(n).
求出目标序列右移0至n-1位置时,不需要移动的人数。将目标序列反转,再求出目标序列右移0至n-1位置时,不需要移动的人数。求不需要移动的人数最大等价于求需要移动的人数最小。复杂度O(n)。
更详细的说:
引进“相对有序”这个概念,当两个人满足C[j]-C[i]==j-i时,两个相对有序。
题目要求最小的总代价,但是我们可以考虑倒过来想,要求最小的总代价亦即求最多有多少人不用移动,亦即相对有序。
然后我们引进一个辅助变量T=C-I,{C-I>=0},T=C[i]-I+N,{C[i]-I<0},那么这个T[i]有什么意义呢?我们知道初始状态的编号是1-N,而目标状态是C[1]-C[N],那么C-I便是从目标状态到初始状态顺时针所要移动的距离,那么如果那么T值相等的两个同学则是相对有序的,亦即不用移动,我们只要找出最大的T然后N-Max(T)就是得到的结果,但是这样还不够,因为刚刚那样只是顺时针所要移动的距离,我们还要计算逆时针的到的结果,从顺时针和逆时针中找到最大的T,然后N-Max(T)才能够是正确结果.0
回复 maxint64发表于2009-09-01 21:33
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
先是物理大发了——以为 b1,b2...bm是连续的
看了牛们的题解 一次ac :)0
回复 柔情使者发表于2009-08-20 15:44
第一遍做的时候没有看题解,自己测了好几遍总是60分,看了n多大牛的解释才恍然大悟,竟然要正反两遍!!!唉,幸亏咱有测试数据,否则我可就惨了...
O(n)的求目标队列算法,都说是冒泡排序,我没看出来,倒是有点像。0
回复 maxiem发表于2009-08-18 20:55
物理自重啊,嘿嘿。
注意要正反两遍哦~
9MS?
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 9ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:9ms
(好像那个冒泡是口胡,大家不要被那个蒙了
program fire;
var
st:array [1..50000,1..2] of longint;
k,final:array [0..50000] of longint;
ex:array [1..50000] of boolean;
p,max,i,n:longint;
begin
fillchar (st,sizeof(st),0);
fillchar (ex,sizeof(ex),0);
fillchar (final,sizeof(final),0);
fillchar (k,sizeof(k),0);
readln (n);
for i:=1 to n do readln (st,st);
final[1]:=1;p:=2;ex[1]:=true;
for i:=1 to n do begin
if ex[st[final[i],1]]=false then begin
final[p]:=st[final[i],1];
ex[st[final[i],1]]:=true;
inc(p);
end
else if ex[st[final[i],2]]=false then begin
final[p]:=st[final[i],2];
ex[st[final[i],2]]:=true;
inc(p);
end;
end;
if p-1<>n then begin
writeln (-1);
halt;
end;
max:=0;
for i:=1 to n do if final[i]>=i then inc(k[final[i]-i]) else inc(k[n-i+final[i]]);
for i:=0 to n-1 do if k[i]>max then max:=k[i];
fillchar (k,sizeof(k),0);
for i:=n downto 1 do if final[i]>=n-i+1 then inc(k[final[i]-n+i-1]) else inc(k[final[i]+i-1]);
for i:=0 to n -1 do if k[i]>max then max:=k[i];
writeln (n-max);
end.0
回复 suning发表于2009-08-14 09:43
啊呜~
一年前误解了题意~
一年后理解了题意~
然后就是1次美妙的ACPS:[误]解[理]解~~~[物理]?
0
回复 fengwuliu发表于2009-08-13 17:20
lgxcgd说的太对了!太感谢了55550
回复 Matt发表于2009-08-11 22:28
NOIP也会考高等数学...由于原图是环,所以置换群可表示为一次循环。作差是个好方法。
但求冒泡排序是怎么作的
0
回复 3830372发表于2009-08-11 21:28
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1504人
提交 4282次
通过率 35%
难度 3提交 讨论 题解 状态
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 尖端才子发表于2009-08-11 11:14
纪念一下……第1500个AC……Flag Accepted
题号 P1008
类型(?) 模拟
通过 1500人
提交 4274次
通过率 35%
难度 3编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 SecretAgent发表于2009-08-10 14:02
置换群是正解编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 yangbei发表于2009-08-07 14:57
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 338ms
├ 测试数据 05:答案正确... 322ms
├ 测试数据 06:答案正确... 306ms
├ 测试数据 07:答案正确... 338ms
├ 测试数据 08:答案正确... 338ms
├ 测试数据 09:答案正确... 322ms├ 测试数据 10:答案正确... 306ms
Accepted 有效得分:100 有效耗时:2270ms
算镜像时偷了点懒,不过也算一遍AC了
0
回复 ja_son发表于2009-08-06 15:44
a:拆环成队,寻求目标队列。
b:b1,b2...bm不是连续的,而且是任意的。只要有成立目标队列,与原来的队列相匹配就可以知道有多少(设为n个)需要移动位置,则代价就是n。
c:目标队列有多种情况,可以反转,也可以左右移动。0
回复 1s发表于2009-08-03 17:56
如对本题有疑问可以参看我的题解:
http://xujieqi.blog.hexun.com/35722312_d.html0
回复 DMKaplony发表于2009-07-30 15:15
当时的时间限制好像是2s。。有个题解说把1定为第一项然后进行冒泡排序。。不过这里是1s 啊。。。也行只有置换群了吧。0
回复 xusc_2009发表于2009-07-28 14:30
看不懂,只好搁浅
什么时候想清楚了再做0
回复 董发表于2009-07-24 19:11
program p1008;
var i,n,k,j,sum1,sum2,ans,max:longint;
a,b,w,d,c:array[0..50005] of longint;begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
w[1]:=1; w[2]:=a[w[1]];
k:=1;repeat
inc(k);
if w[k-1]=a[w[k]] then w[k+1]:=b[w[k]]
else if w[k-1]=b[w[k]] then w[k+1]:=a[w[k]]
else begin
writeln(-1);
exit;
end;
until k=n;
if w[n+1]<>w[1] then
begin
writeln(-1);
exit;
end;for i:=1 to n do
begin
a[i]:=w[i]-i;
b[i]:=w[n-i+1]-i;
if a[i]<0 then a[i]:=a[i]+n;
if b[i]<0 then b[i]:=b[i]+n;
inc(c[a[i]]);
inc(d[b[i]]);
end;
for i:=0 to n-1 do
begin
if ans<c[i] then ans:=c[i];
if ans<d[i] then ans:=d[i];
end;
writeln(n-ans);
end.0
回复 我飞发表于2009-07-23 21:00
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 93狒狒发表于2009-07-23 20:59
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
秒杀......
0
回复 fjxmlhx发表于2009-07-22 13:15
置换群,做2n次,顺时针和逆时针.
对于一个置换,最小操作费用是所有循环长度的和.因此实际上是找出2n个置换中哪个置换循环长度为1的数量最多.0
回复 340508965发表于2009-07-21 15:01
⊙﹏⊙b汗
不知道的以为这是数学竞赛......
...
我的数论与图论可以说脑袋里空白一片.........
怎么办,我的竞赛啊
........算了 看了题解 大家写的
总算弄懂这道题了
先前以为b1,b2,b3..bm是连续的
没想到是任意的!!!!!!!!!诶 叹悲歌未切 为撼奈何编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
总算AC了
program p1008;
var i,n,k,j,sum1,sum2,ans,max:longint;
a,b,w,d,c:array[0..50005] of longint;begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
w[1]:=1; w[2]:=a[w[1]];
k:=1;repeat
inc(k);
if w[k-1]=a[w[k]] then w[k+1]:=b[w[k]]
else if w[k-1]=b[w[k]] then w[k+1]:=a[w[k]]
else begin
writeln(-1);
exit;
end;
until k=n;
if w[n+1]<>w[1] then
begin
writeln(-1);
exit;
end;for i:=1 to n do
begin
a[i]:=w[i]-i;
b[i]:=w[n-i+1]-i;
if a[i]<0 then a[i]:=a[i]+n;
if b[i]<0 then b[i]:=b[i]+n;
inc(c[a[i]]);
inc(d[b[i]]);
end;
for i:=0 to n-1 do
begin
if ans<c[i] then ans:=c[i];
if ans<d[i] then ans:=d[i];
end;
writeln(n-ans);
end.0
回复 zsy90943发表于2009-07-18 00:51
构造巧妙、、看来还是要学好数论和图论额、、、、0
回复 POM无敌牛B发表于2009-07-16 11:47
编译通过...
├ 测试数据 01:运行超时...
├ 测试数据 02:运行超时...
├ 测试数据 03:运行超时...
├ 测试数据 04:运行超时...
├ 测试数据 05:运行超时...
├ 测试数据 06:运行超时...
├ 测试数据 07:运行超时...
├ 测试数据 08:运行超时...
├ 测试数据 09:运行超时...├ 测试数据 10:运行超时...
Unaccepted 有效得分:0 有效耗时:0ms
无奈 哪位哥哥救救我0
回复 yxy发表于2009-06-16 18:16
把置换解释成度为2图,真有才.
求出序列,正反分别做一次差就行了.0
回复 sxpeter发表于2009-06-14 16:56
讲建环吧。数组w表示环,我用的是一种类似并查集的方法。
begin
read(n);
for i:=1 to n do read(a[i],b[i]);
t:=2;w[1]:=1;w[2]:=a[1];
while true do begin
if a[w[t]]<>w[t-1]then w[t+1]:=a[w[t]]//是否在左边
else if b[w[t]]<>w[t-1]then w[t+1]:=b[w[t]]//是否在右边
else begin writeln(-1);halt;end;//失败判断
inc(t);
if t>n then break;
end;
if w[n+1]<>w[1]then begin writeln(-1);halt;end;//本句一定要加!!!!!!
end.0
回复 lgxcgd发表于2009-05-17 20:24
首先把这个圈看做一个图,每个同学看做一个顶点。因为要形成环,所以每个顶点的度必须为2。如果存在度数不为2的顶点,那么整个图无法构成一个环,即“无论怎么调整都不能符合每个同学的愿望”输出-1。
如果是一个环,那么就遍历图,生成以第1个顶点为开头的序列。现在就要求出最小移动的代价。
在理解题意所述的调整方式中,要注意实际上就是把M个在错误位置上的人移动到正确的位置上,代价为M。一次下令移动即可。
假如生成的目标序列为1,5,3,2,4。我们现在就需要比较它和初始状态1,2,3,4,5,看有几个人离开了原来的位置。但这个序列实际代表的是一个环,而且方向正反有两种,就需要把初始序列正反分别转N次,和得到的序列比较,看其中最少有几个位置上的人编号不相同,就得到了我们要求的最小代价。
上述方法有大量冗余。但可以发现转来转去不管怎么转,任意两个人之间的相对位置关系在这过程中都不会变。于是想到做差,如果差小于0则加上N。
1 5 3 2 4
- 1 2 3 4 5
0 3 0 3 4
这表示序列1,5,3,2,4不转动时1,3两个人在原来的位置上,转动3个位置后5和2两个人在原来的位置上,转动4个位置后只有4一个人会在原来的位置上。这就是说,1,5,3,2,4与1,2,3,4,5在旋转后最多有2个位置上的人编号相同,即最少有3个位置上的人编号不相同。同理要反转再求一次。记录每个不同的差值的个数,取其最大值P,即不调换次数最大的。结果N-P就是调换次数最小的。
0
回复 src250发表于2009-05-14 08:27
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
切记:重新构图时一定要对数组清空!我的第一次只有50分,就是这个原因!
0
回复 love19960108发表于2009-04-26 17:59
这题可以用C++这样做么??
#include <iostream>
#include <cassert>
using namespace std;
long N,seq[50001],p=1;
class{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2){
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2) return true;
return false;
}
public:
bool AddE(long v1,long v2){
if(isnbr(v1,v2)) return true;
else if(nbr[v1][0]==2||nbr[v2][0]==2) return false;
else{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i){
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++){
if(!flag[nbr[i][j]]){
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve(){
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N;
b=seq[i]-(N+1-i);
if(b<0) b+=N;
if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main(){
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++){
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2)){
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
return 0;
}0
回复 voyagec2发表于2009-03-18 15:53
难理解,不过算法很精妙0
回复 pRoevollove发表于2009-02-25 23:49
天,把(p[i]-i+n)mod n理所当然地打成了abs(p[i]-i)
结果一直50分……还一直以为自己构造错了……ps 我可以过楼下的范例哦
0
回复 ufo172849z发表于2009-01-24 23:05
ms楼下的程序不能处理这种反例(测试数据还是不够强啊)
6
2 3
1 3
1 2
5 6
4 6
4 5
应该输出-1的吧?因为是两个环var a,b:array[0..50000]of longint;
c:array[0..50000,1..2]of longint;
d:array[0..50000]of boolean;
i,j,k,m,n,max:longint;
can:boolean;begin
readln(n);
for i:=1 to n do
readln(c,c);
b[0]:=c[1,1]; b[n]:=c[1,1];
fillchar(d,sizeof(d),0);
k:=1;
can:=true;
for i:=1 to n-1 do
begin
if d[k] then can:=false;
b[i]:=k; d[k]:=true;
if b=c[k,1] then k:=c[k,2]
else if b=c[k,2] then k:=c[k,1]
else can:=false;
if not can then break;
end;
if can then
if b[n]<>k then can:=false;
if can then
begin
max:=-1;
fillchar(a,sizeof(a),0);
for i:=1 to n do
inc(a[(b[i]-i+n) mod n]);
for i:=0 to n-1 do
if a[i]>max then max:=a[i];
fillchar(a,sizeof(a),0);
for i:=1 to n do
inc(a[(b[n-i+1]-i+n)mod n]);
for i:=1 to n-1 do
if a[i]>max then max:=a[i];
writeln(n-max);
end
else
writeln(-1);
end.0
回复 tangdongjian发表于2009-01-23 22:17
我在做镜像时把原先max直接覆盖上了,注意0
回复 永恒888发表于2009-10-26 22:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 tangkunjie发表于2009-06-04 19:50
挺烦人的题目0
回复 ykspeter发表于2008-11-13 20:32
program fire(input,output);
var
n,i,j,k,max,v:longint;
a:array[0..100000,1..2] of longint;
b,c:array[0..100000] of longint;
begin
readln(n);
for i:=1 to n do readln(a,a);
for i:=1 to n do
begin
k:=0;
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if (k=4) or (k=3)
then begin
writeln('-1');
exit
end
end;
b[1]:=1;i:=2;k:=a[1,1];j:=1;
repeat
b[i]:=k;
inc(i);
v:=k;
if a[k,1]<>j
then k:=a[k,1]
else k:=a[k,2];
j:=v;
until i=n+1;
fillchar(c,sizeof(c),0);
for i:=1 to n do inc(c[(b[i]-i+n)mod n]);
for i:=0 to n-1 do
if c[i]>max
then max:=c[i];
fillchar(c,sizeof(c),0);max:=0;
for i:=1 to n do inc(c[(b[n-i+1]-i+n)mod n]);
for i:=n-1 downto 0 do
if c[i]>max
then max:=c[i];
writeln(n-max);
end.0
回复 getuojian发表于2008-11-10 13:38
#include<stdio.h>
#include<memory.h>const int maxn=50010;
int n;
int f[maxn][2];
int goal[maxn];
int ans=maxn;
int hash[maxn];bool SET_ORI(){
bool flag[maxn];
memset(flag, true, sizeof(flag));
goal[1]=1; flag[1]=false;
for (int i=1; i<=n-1; i++){
if (flag[f[goal[i]][0]]){
goal=f[goal[i]][0];
flag[f[goal[i]][0]]=false;
continue;
}
if (flag[f[goal[i]][1]]){
goal=f[goal[i]][1];
flag[f[goal[i]][1]]=false;
continue;
}
return false;
}
if ((goal[n]!=f[1][0]) && (goal[n]!=f[1][1]))
return false;
return true;
}
int SWAP(int i, int j){
int t=goal[i];
goal[i]=goal[j];
goal[j]=t;
return 0;
}int min(int i, int j){
return i>j?j:i;
}
int HASH(){
for(int i=1; i<=n; i++)
hash[i]=goal[i]-i+n;
return 0;
}int CALC(){
int temp[maxn*2], back=0;
memset(temp, 0, sizeof(temp));
for (int i=1; i<=n; i++)
temp[hash[i]%n]++;
for (int i=1; i<=2*n-1; i++)
if (temp[i] > back)
back=temp[i];
return back;
}int main(){
freopen("fire.in", "r", stdin);
freopen("fire.out", "w", stdout);
scanf("%d", &n);
for (int i=1; i<=n; i++)
scanf("%d %d", &f[i][0], &f[i][1]);
if (!SET_ORI()){
printf("-1");
return 0;
}
//forward
HASH();
ans=min(ans, n-CALC());
//backward
for (int i=1; i<=n/2; i++)
SWAP(i,n-i+1);
HASH();
ans=min(ans, n-CALC());printf("%d", ans);
return 0;
}0
回复 IVORY发表于2008-11-06 10:46
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
CHEAT的...
0
回复 storey p发表于2008-11-05 14:19
回447389831:
exit换成halt0
回复 FenXy发表于2008-11-04 08:28
艺术p2450
回复 hlq发表于2008-11-01 14:31
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms求不在位置上的人数
a【i】 第i位上的同学编号
for i:=1 to n do
begin
inc(b[(a[i]-i+n) mod n])
end;
max:=0;
for i:=0 to n-1 do
if b[i]>max then max:=b[i];
fillchar(b,sizeof(b),0);
for i:=1 to n do
begin
inc(b[(a[i]-(n-i+1)+n)mod n]);//对称
end;
for i:=0 to n-1 do
if b[i]>max then max:=b[i];0
回复 Will~骷髅发表于2008-10-30 21:37
编译通过...
├ 测试数据 01:运行超时...
├ 测试数据 02:运行超时...
├ 测试数据 03:运行时错误...|错误号: -1073741819
├ 测试数据 04:运行时错误...|错误号: -1073741819
├ 测试数据 05:运行时错误...|错误号: -1073741819
├ 测试数据 06:运行时错误...|错误号: -1073741819
├ 测试数据 07:运行时错误...|错误号: -1073741819
├ 测试数据 08:运行时错误...|错误号: -1073741819
├ 测试数据 09:运行时错误...|错误号: -1073741819├ 测试数据 10:运行时错误...|错误号: -1073741819
Unaccepted 有效得分:0 有效耗时:0ms
怎么会这样???
0
回复 悲伤逆流成河发表于2008-10-28 22:13
#include <iostream>
#include <fstream>
using namespace std ;int hash[50001];
int n , i , j , t , maxs(0) ;inline void HASH ( int e[] )
{
for ( i = 1 ; i <= n ; i++ )
{
e[i] -= i ;
if ( e[i] < 0 ) e[i] += n ;
hash[e[i]]++ ;
}
for ( i = 0 ; i < 50001 ; i++ )
if ( maxs < hash[i] ) maxs = hash[i] ;
}int main(){
ifstream fin ("fire.in") ;
ofstream fout ("fire.out") ;fin >> n ;
int e[n+1] , h[n+1][2] , e2[n+1];
bool f[n+1] ;
for ( i = 1 ; i <= n ; i++ )
{
f[i] = false ;
fin >> h[i][0] >> h[i][1] ;
}
e[1] = 1 ;
f[1] = true ;
for ( i = 2 ; i <= n ; i++ )
{
if ( e < 0 ) { fout << -1 << endl ; exit(0) ; }
if ( !f [ h[ e ][0] ] ) e[i] = h[ e ][0] ;
if ( !f [ h[ e ][1] ] ) e[i] = h[ e ][1] ;
f[ e[i] ] = true ;
}
for ( i = 1 , j = n ; i <= n ; i++,j-- ) e2[j] = e[i] ;
HASH ( e ) ;
memset ( hash , 0 , sizeof ( hash ) ) ;
HASH ( e2 ) ;
fout << n - maxs << endl ;
}0
回复 evelynhe发表于2008-10-26 16:31
“置换群思想...今天刚明白...先构造新数列(要构造两次,否则只有70分),然后向右计算相对位置差,然后累加记录数组,然后用N减去相对位置差累加值最大的,就是答案... ”
这是真的
0
回复 true1023发表于2008-10-25 09:32
置换群的基本概念
利用原序列和目标序列每个元素的绝对位置差来求出原序列每个元素对于目标序列的相对位置,找相对位置相同的最多的元素数,用总元素数减去它即为结果。0
回复 447389831发表于2008-10-21 09:45
program fire(input,output);
var
n,i,j,k,max,v:longint;
a:array[0..100000,1..2] of longint;
b,c:array[0..100000] of longint;
begin
readln(n);
for i:=1 to n do readln(a,a);
for i:=1 to n do
begin
k:=0;
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if (k=4) or (k=3)
then begin
writeln('-1');
exit
end
end;
b[1]:=1;i:=2;k:=a[1,1];j:=1;
repeat
b[i]:=k;
inc(i);
v:=k;
if a[k,1]<>j
then k:=a[k,1]
else k:=a[k,2];
j:=v;
until i=n+1;
fillchar(c,sizeof(c),0);
for i:=1 to n do inc(c[(b[i]-i+n)mod n]);
for i:=0 to n-1 do
if c[i]>max
then max:=c[i];
fillchar(c,sizeof(c),0);max:=0;
for i:=1 to n do inc(c[(b[n-i+1]-i+n)mod n]);
for i:=n-1 downto 0 do
if c[i]>max
then max:=c[i];
writeln(n-max);
end.
90 分,牛人门帮看下把0
回复 cnfnje1发表于2008-10-17 18:12
置换群.....是什么?
readln(n);
for i:=1 to n do readln(a[i],b[i]);
c[1]:=1; c[2]:=a[1];
for i:=3 to n do if c=a[c] then c[i]:=b[c]
else if c=b[c] then c[i]:=a[c]
else begin writeln(-1); halt end;
if c[n]<>b[1] then begin writeln(-1); halt end;
fillchar(d,sizeof(d),0);
for i:=1 to n do inc(d[(c[i]-i+n)mod n]);
for i:=0 to n-1 do if d[i]>m then m:=d[i];
fillchar(d,sizeof(d),0);
for i:=1 to n do inc(d[(c[i]+i-1)mod n]);
for i:=0 to n-1 do if d[i]>m then m:=d[i];
writeln(n-m);
是么?0
回复 lyrics发表于2008-10-12 19:55
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
技巧性比较强吧,楼下不必构造2次,计算时从头至尾算一次,再倒过来算一次就行了
0
回复 LV.唱响发表于2008-10-05 08:38
置换群思想...今天刚明白...先构造新数列(要构造两次,否则只有70分),然后向右计算相对位置差,然后累加记录数组,然后用N减去相对位置差累加值最大的,就是答案...
0
回复 宇智波带波斯猫发表于2008-10-05 08:33
Flag Accepted
题号 P1008
类型(?) 其它
通过 1065人
提交 3000次
通过率 35%
难度 3第3000个提交的
0
回复 鸳鸯羡发表于2008-09-28 18:19
#include <iostream>
using namespace std ;int hash[50001];
int n , i , j , t , maxs(0) ;inline void HASH ( int e[] )
{
for ( i = 1 ; i <= n ; i++ )
{
e[i] -= i ;
if ( e[i] < 0 ) e[i] += n ;
hash[e[i]]++ ;
}
for ( i = 0 ; i < 50001 ; i++ )
if ( maxs < hash[i] ) maxs = hash[i] ;
}int main(){
cin >> n ;
int e[n+1] , h[n+1][2] , e2[n+1];
bool f[n+1] ;
for ( i = 1 ; i <= n ; i++ )
{
f[i] = false ;
cin >> h[i][0] >> h[i][1] ;
}
e[1] = 1 ;
f[1] = true ;
for ( i = 2 ; i <= n ; i++ )
{
if ( e < 0 ) { cout << -1 << endl ; exit(0) ; }
if ( !f [ h[ e ][0] ] ) e[i] = h[ e ][0] ;
if ( !f [ h[ e ][1] ] ) e[i] = h[ e ][1] ;
f[ e[i] ] = true ;
}
for ( i = 1 , j = n ; i <= n ; i++,j-- ) e2[j] = e[i] ;
HASH ( e ) ;
memset ( hash , 0 , sizeof ( hash ) ) ;
HASH ( e2 ) ;
cout << n - maxs << endl ;
}80分
0
回复 月光疾风发表于2008-09-25 13:03
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
纪念我第200次提交!过第79题。。。。0
回复 ghostplant发表于2008-09-20 19:48
#include <iostream>
#include <fstream>
#include <cassert>
using namespace std;
long N,seq[50001],p=1;
class{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2){
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2) return true;
return false;
}
public:
bool AddE(long v1,long v2){
if(isnbr(v1,v2)) return true;
else if(nbr[v1][0]==2||nbr[v2][0]==2) return false;
else{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i){
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++){
if(!flag[nbr[i][j]]){
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve(void){
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N;
b=seq[i]-(N+1-i);
if(b<0) b+=N;
if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main(){
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++){
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2)){
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
return 0;
}0
回复 zzh19950802发表于2008-09-17 19:29
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案错误... ├ 标准行输出
├ 错误行输出
├ 测试数据 05:答案错误... ├ 标准行输出
├ 错误行输出
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 462ms
├ 测试数据 08:答案正确... 369ms
├ 测试数据 09:答案正确... 384ms
├ 测试数据 10:答案错误...程序输出比正确答案长
为什么我的程序不对?
#include <iostream>
using namespace std;
#define MAXN 50000
int man[MAXN+2][2];
int cercle[MAXN+2]={0,1};
int used[MAXN+2]={0};
int reduce[2][MAXN+2]={0};
int n;
int main()
{
long i,p,q=1,t;
int max=0;
cin>>n;
for (i=1;i<=n;i++) cin>>man[i][0]>>man[i][1];
p=man[q][1];
for (i=2;i<=n+1;i++)
{
if (man[q][1]==p)
{
p=q;
q=man[q][0];
}
else
{
if(man[q][0]!=p) break;
p=q;
q=man[q][1];
}
if(used[q]) break;
else used[q]=1;
cercle[i]=q;
}
if (i<=n+1) cout<<-1;
else
{
for (i=1;i<=n;i++)
{
if((t=cercle[i]-i)<0) t+=n;
reduce[0][t]++;
if (reduce[0][t]>max) max=reduce[0][t];
if ((t=cercle[i]-n+i-1)<0) t+=n;
if (reduce[1][t]>max) max=reduce[1][t];
}
cout<<n-max;
}
return 0;
}0
回复 liaorc发表于2008-09-16 17:56
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 cxy450090074发表于2008-09-04 13:34
oh no0
回复 Lost.G发表于2008-08-22 15:49
我在想``怎么样才能不看错这题呢0
回复 bonism发表于2008-08-14 21:30
时间复杂度O(N)。。。原来我一直把题意理解错。。。囧!!。。
关于“置换群”,请看LRJ的《算法艺术与信息学竞赛》P245那一小节,还是比较好理解的。
0
回复 lemon_cn发表于2008-08-08 15:55
热烈庆祝用pascal AC的第二题~
p.s.我是C++的~~0
回复 oipn4e2发表于2008-08-05 21:36
解决效率不高,但AC了。0
回复 notblack发表于2008-08-01 09:17
用距离来分类,统计在原位的最大人数,奇怪的是
b[1]:=1;
b[2]:=a[1,1];
b[n]:=a[1,2];建环的时候,上面的改成
b[1]:=1;
b[2]:=a[1,2];
b[n]:=a[1,1];最后一个点却过不了,太奇怪了.
0
回复 332404521发表于2008-07-14 13:53
对于初三刚刚中考完的我,要理解这题的意思是万万不能的。。。
看题解我知道了应该怎么做,但那不是我的,所以不做了。。。
哪天能证明出来那啥再来做0
回复 Sheeta发表于2007-11-14 15:45
好简单啊
直接贪啊
(P.S.置换群?什么东东...)0
回复 mingyueyucai发表于2007-11-09 21:22
我代码写了老长老长,结果还是只过了8个点,有没有搞错?
我想请问一下,我和大家的一样,先排列出目标状态.然后确定初始状态时使得最多的人在目标位置上,然后交换.但是得到的答案总是偏大一点.
然后我又把所有可以使最多的人在原位目标位置上的可能都尝试了一编(包括正反两个目标状态),结果还是只能过8个点,有2个点死都过不了!
我的算法有什么问题吗?0
回复 luanjiyang发表于2007-11-08 08:44
很委琐的说 我提交了8遍。。
0→0→10→10→10→10→70→AC- -||
0
回复 lonelycorn发表于2007-11-05 23:31
数论……好底歇的东西。0
回复 gamejifan发表于2007-11-04 11:15
这题的叙述,让我误会了一年多。tzkq……3q..要早知道是这种意思早就ac了这题。。显然没什么大意思,看过组合数学或者学过群论的都懂。。ms跟polya计数法那个循环的意思。。写的时候竟然因为交换的时候写错一个字母wa。我汗。
0
回复 Alexandria发表于2007-11-01 13:33
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
好强大的题啊,不看题解还真不会!
0
回复 clfhaha1234发表于2007-10-30 18:09
请问什么是置换群啊?可以讲讲吗?………………0
回复 rleepas发表于2007-10-30 13:18
楼下都是正解?
......0
回复 Ice_Msk发表于2007-10-18 20:35
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
什么是置换群?不知道。。。照样过。。。。
0
回复 junlonely发表于2007-10-18 20:13
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 江南不才发表于2007-10-11 16:19
排序法这里会超时~~~~~
比赛的时间是2S~~
这里是1S~~
(_)0
回复 秒杀群众发表于2007-10-10 17:05
居然是置换群。。。
对了。。。什么是置换群...
上网查啊!!!0
回复 southstarj1发表于2007-10-02 18:50
思想:
置换群。(相关知识自己查)
对于一组数据,按各人的意愿排出一个序列,
如果无法排出,就输出-1。
再将环状序列变成链状,则这个目标序列为一个置换群,
与原序列(按1到n的一列)满足:
交换的最少人数等于目标序列与原序列不重合的人数。
因为总共有2n个目标序列(正反各n种),都算一遍就行了。步骤:
1. 读入数据;
2. 构造一个目标序列;
3. 统计该序列中元素位置与该元素在原序列位置的差值(同一方向)为i{i ∈ [0, n)}的元素个数;
4. 将该序列的反序统计一遍;
5. 从这些数据中选取一个最大的值max;
6. 输出n - max;注意:
构造目标序列时判断能否构造的条件;
统计一次差值的复杂度是O(n);
统计差值的目的是求与原序列最多的重合人数;0
回复 wangjin5发表于2007-09-19 22:38
好经典的题奥
确实有难度0
回复 the_melody发表于2007-09-03 17:58
Accepted 有效得分:100 有效耗时:0ms
好经典的题奥0
回复 richardxx发表于2007-08-22 17:36
下面程序是错的,不好意思,弄错地方了....0
回复 sm-star发表于2007-08-21 15:18
题目所求就是每次进行连续交换的人数总和,这样,一个看似复杂的题目就变的异常的简单了!0
回复 wasyyyy发表于2007-08-11 02:05
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
HOHO~~~看讨论的时候看到有人提到‘置换群’这个东西,突然想起来我刚买的一本组合数学上有这么一块东西,就拿过来看了。。。。
然后就出现上面的东西了。。。。置换群,本来想求轮换的,发现轮换比较多,还是找不参与交换的比较好记。。。。优化的方法。。。我看了下好象不只一个人讲过了。。。而且似乎我跟他们的都一样(没仔细看)所以就不说了。。。效率是O(n)的。。不用建环。
0
回复 angieqiu发表于2007-08-10 22:49
怎么判断建环失败啊?我的程序虽然AC但总觉得方法很傻0
回复 梦ぁ逍遥发表于2007-07-17 13:45
想到了用t[i]=b[i]-i表示环
却没想到镜像..十分感谢visister
让我从90分中挣扎出来...0
回复 visister发表于2007-06-01 00:12
首先明显地可以知道我们需要对于目标状态建立出一个环。如果无法建立这个环,那么结果一定是-1,当建立好环以后可以知道最小移动代价一定等于最少的不在目标位置上的人数。那么我们可以对目标环进行顺时针旋转1~n-1之中任意一个,答案就一定等于旋转中的不在自己位置上的人数最少的那样的环的状态。但是对于50000的数据,我们如果要将环旋转1~n-1次,那么总共加上判断不在自己位置上的人数时间复杂度为O(n^2),显然在限定时间内是无法出解的。因此我们进行逆向思维:不在自己位置上最少的人数就一定会等于总人数减去在自己位置上最多的人数(仔细想想),那么我们就将该问题转化为了求在自己的位置上最多的人数,这样一来,我们对初始目标环中每一个位置进行判断需要旋转多少次可以回到自己位置上,每一个人的选择都将映射到[0..n-1]的数组中,选取当中最大的情况就为所求,但是考虑到环可以反转,那么我们还需要将环再求一次镜像,就可以得到初始目标需要旋转多少次可以得到在自己位置上最多的人数的环的状态,最后通过总的人数减去它即为问题所求,时间复杂度为O(n);0
回复 pyh119发表于2006-11-16 20:11
哪个人不小心失火了找我啊!!!PS:我是安徽省芜湖市119接线员....
0
回复 maomingming发表于2006-11-06 18:40
考虑旋转后最多可能重合的情况,另要注意圈可以反过来0
回复 qian5发表于2006-09-30 21:35
直接输出‘-1’有一个点过0
回复 BambooLeaf发表于2006-09-26 18:17
见过的最牛最简单的方法……
将此题转换为冒泡排序,记录下所有交换的次数和两数间的距离,加上就行了……—__—|||
具体是这样的,我们反向思维,本来是要求一个有序数列求出成为无序数列的代价,现在我们把无序数列(即目标数列)进行冒泡排序,然后……就是这样……
看完之后,偶巨汗……0
回复 xcjzj发表于2006-09-26 17:18
每组数据确定两组相对位置关系,并且这两组互为镜像。
对于某一种排列方式,不在需要位置上的人数即为当前状态到目标状态的最小代价。
先找出其中一种排列方式。由于目标状态可以通过旋转而使得部分人的变化次数减少,所以找出每个人通过某一固定方向旋转到达目标位置的旋转次数。找到某一次数,使得拥有这个次数的人数最多。那么,通过旋转这一最多人拥有的次数,即可使得尽可能多的人不通过交换直接到达目标位置。于是,不拥有这一旋转次数的人数即为这一状态下的最小代价。
然后,用现在的目标状态找出其镜像状态,并且用上述方法再找一遍最小代价,与前面的结果比较,较小值即为答案。
另外,题目中会出现一些无解的情况:
1.某个人被“要”的次数多于两次,也就是说有多于两个的人想要与他(她)邻座,那么无解。
2.根据要求得出的目标状态为多于一个的环,也无解。0
回复 东邪歪刀发表于2006-07-28 17:27
提交了若干次……残念……0
回复 sugar发表于2006-07-28 16:26
这题比赛时真有人ac?
真不好想
为什么得开longint啊?0
回复 晶星发表于2006-07-25 13:29
排列本质不同的只有二种 正着和反着的
检验几个人不在位置上用数学方法:)模拟法超时的0
回复 tzkq发表于2006-07-23 04:37
注意别误解题意 b1,b2....bm并不指连续位置上的数0
回复 Coldwings发表于2006-01-26 09:21
可以用群论证明:如果有k个人不在自己的位置上,那么要且仅要k的代价,即可使这些人归位剩下的..很简单了吧...
0
回复 lemon_cn发表于2008-08-08 15:55
热烈庆祝用pascal AC的第二题~
p.s.我是C++的~~
0回复 yingjiangyu发表于2015-02-15 21:55
打‘Wrong!’有50分。。0
回复 东大微雕发表于2015-02-07 15:20
这道题真是太好了。奇妙无穷。
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
int a[50005];
int size;
void go(){
int i, j;
int ans = 0;
int dis[50005];
memset(dis, 0, sizeof(dis));
for (i = 1; i <= size; i++){
int d = (a[i] - i + size) % size;
dis[d]++;
}
for (i = 0; i < size; i++){
if (ans < dis[i])
ans = dis[i];
}
memset(dis, 0, sizeof(dis));
for (i = 1; i <= size; i++){
int d = (a[size+1-i]-i+size) % size;
dis[d]++;
}
for (i = 0; i < size; i++){
if (ans < dis[i])ans = dis[i];
}
cout << size-ans << endl;
}
int main(){
freopen("in.txt", "r", stdin);
int neibor[50005][2];
int i;
cin >> size;
for (i = 1; i <= size; i++){
scanf("%d%d",&neibor[i][0],& neibor[i][1]);
}
bool used[50005];
memset(used, 0, sizeof(used));
a[1] = 1;
used[1] = true;
for (i = 2; i <= size; i++){
int last = a[i - 1];
if (!used[neibor[last][0]]){
a[i] = neibor[last][0];
used[a[i]] = true;
}
else if (!used[neibor[last][1]]){
a[i] = neibor[last][1];
used[a[i]] = true;
}
else {
cout << -1 << endl;
return 0;
}
}
if (neibor[1][0] != a[size] && neibor[1][1] != a[size]){
cout << -1 << endl;
return 0;
}
go();
return 0;
}0
回复 3516发表于2014-07-30 08:59
include<stdio.h>include<string.h>
int data[50001][2],shi[50001],a[50001];
int main()
{
int n,i,j,qian,hou; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d%d",&data[i][0],&data[i][1]); } a[1]=1;shi[a[1]]=1 for(i=2;i<=n;i++) { qian=data[a[i-1]][0]; hou=data[a[i-1]][1]; if(shi[qian]==0) { a[i]=qian; shi[qian]=1; } else if(shi[hou]==0) { a[i]=hou; shi[hou]=1; } else { printf("-1"); return 0; } } int temp=0,max=0; memset(shi,0,sizeof(shi)); for(i=1;i<=n;i++) { temp=(n+a[i]-i+1)%n; shi[temp]++; } for(i=0;i<n;i++) { if(max<shi[i]) { max=shi[i]; } } memset(shi,0,sizeof(shi)); for(i=1;i<=n;i++) { temp=(n+a[n-i+1]-i+1)%n; shi[temp]++;
}
for(i=0;i<n;i++)
{
if(max<shi[i])max=shi[i];
}
printf("%d",n-max);
}0
回复 S.Y.F发表于2013-08-31 14:04
题解
1111111129回复于2014-08-13 11:52
orzorzorz0
回复 S.Y.F发表于2013-07-29 16:55
从10、到30、到100。。。。。。
题解:http://blog.163.com/syf_light_feather/blog/static/223755067201362945326756/0
回复 vcvycy发表于2013-06-30 00:56
20 30 40 50 70 分都有~泪流满面.
Accepted100
772 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:55:05
Wrong Answer70
613 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:53:24
Wrong Answer70
686 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:45:35
Wrong Answer70
856 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:42:12
Wrong Answer70
803 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:37:26
Wrong Answer70
882 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:22:39
Wrong Answer70
1145 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:20:30
Wrong Answer10
733 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:11:30
Wrong Answer50
723 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:04:20
Wrong Answer50
781 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:55:49
Wrong Answer40
656 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:49:49
Wrong Answer40
758 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:44:00
Time Exceeded30
7160 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:38:22
Time Exceeded20
7135 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:35:080
回复 SEX丶Elope发表于2013-02-16 10:10
点击查看程序源码+详细题解
cuichen回复于2014-09-09 09:24
怎么又是你??你有什么企图?骗访问量???垃圾!0
回复 qyjubriskxp发表于2010-07-09 21:31
再一次体会到c++流的悲剧,秒杀和3s原来只是输入方式的不同,杯具~~
yuyilahanbao回复于2014-01-24 11:47
从c转到c++第一次不AC(除去忘记把语言有c改为c++的)就是因为c++输入输出的问题
从那次起,我的c++的输入都是用scanf和printf了
因为
保险
安全
我记不清cin是<<还是>>
printf和scanf相对更灵活
....0
回复 slm发表于2010-03-16 18:27
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
嘿嘿0
回复 superyoi发表于2009-11-10 11:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
superyoi killed p1008 with a headshot by awp
0
回复 200853349发表于2009-11-10 10:49
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
当我看到众位神牛打出“置换群”三个字后,我在黑书百度GOOGLE维基百科逛了得有一个半小时多然后回来AC了。。。
思路和strini神牛的基本一样。
0
回复 sinb发表于2009-11-09 13:02
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
其实很简单,不要想复杂了,先是想办法构成,然后用置换群的方法即可ac。0
回复 香蕉派发表于2009-11-06 11:29
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
虽然不懂什么叫置换群,但是思路还是很清晰的。。0
回复 赏金神侠PPF发表于2009-11-05 11:45
一星星纪念~0
回复 strini发表于2009-10-30 22:11
根据群论原理,任何置换群都可以分解为若干个循环节。显然,这道题目就是冲着这点来的。因为如果某循环的长度为L,那么本题中只需要代价为L的操作。注意,这里的L!=1,这是因为只有一个人的循环节不需要任何代价的操作。到这里才只能拿三十分,因为圈是可以旋转的,常规方法需要O(n^2)才能解决。不妨这里以编号为1的人为基准,定义每个人到自己应该所在位置的距离。距离不超过n-1。可以通过最大值来寻找能在自己位置上的最多的人数(因为距离为x的人在旋转x次后转到自己的位置上),那么在比较好的情况下,可以优化到O(n)。TIME: 1H
SUBMIT:
1 70 Error: 发现希望相邻是不精确的,于是改了个搜索方向。(以为题目给定的是按照左右方向,白书说过不能“假定”!)。
2 90 Error: 终于明白要取两个搜索方向的最大值。
3 Accepted.
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 skykey发表于2009-10-29 17:58
#include<iostream>
using namespace std;
int n;
int a[50001],b[50001],c[50001];
int aim[50001];
void G_MAP()
{
bool mark[50001]={false};
int p=1,r=1;
while(p<=n)
{
aim[p]=r;mark[r]=true;p++;
if(!mark[a[r]])r=a[r];
else if(!mark[b[r]])r=b[r];
else if(p<=n){cout<<-1;exit(0);}
}
}
int COMPULATE()
{
int max=0;
int t;
int record[2][50001];
for(int i=1;i<=n;i++)record[0][i]=record[1][i]=0;
for(int i=1;i<=n;i++)
{
if((t=aim[i]-i)<0)t+=n;
record[0][t]++;
if(record[0][t]>max)max=record[0][t];
if((t=aim[i]-(n+1-i))<0)t+=n;
record[1][t]++;
if (record[1][t]>max)max=record[1][t];
}
return max;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{scanf("%d%d",&a[i],&b[i]);c[a[i]]++;c[b[i]]++;}
for(int i=1;i<=n;i++)if(c[i]!=2){cout<<-1;return 0;}G_MAP();
int T=COMPULATE();
cout<<n-T;
}0
回复 song19931218发表于2009-10-27 20:11
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
考虑两种情形(貌似这两种情形很像,但又真的不同,后来才想起,在化学的手性碳原子那部分遇到过类似情况。。。)
然后就是运用置换群的知识0
回复 Aries_C发表于2009-10-25 08:24
正反两遍...两遍...<幽幽的声音飘远..>不然就是70分啊...
不看题解的情况下竟然自己想到了...
记得以前老师给我们做过这题的..细节什么的现在做又忘记了..唉..
0
回复 国防安全员001发表于2009-10-21 22:00
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1701人
提交 4835次
通过率 35%
难度 3题目表述有问题。。
0
回复 liubosen发表于2009-10-21 21:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
yaaaayyayayyayayayayayayayayayayayayayayayyaayayayayayayyaayayayay
var
n,max,i:longint;
a,b,c,d:array[0..50001] of longint;
begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
c[1]:=1;
c[2]:=a[1];
for i:=3 to n do
if c=a[c] then c[i]:=b[c]
else
if c=b[c] then c[i]:=a[c]
else begin
writeln(-1);
halt
end;
if c[n]<>b[1] then
begin
writeln(-1);
halt
end;
fillchar(d,sizeof(d),0);
for i:=1 to n do
inc(d[(c[i]-i+n)mod n]);
for i:=0 to n-1 do
if d[i]>max then max:=d[i];
fillchar(d,sizeof(d),0);
for i:=1 to n do
inc(d[(c[i]+i-1)mod n]);
for i:=0 to n-1 do
if d[i]>max then max:=d[i];
writeln(n-max);
end.0
回复 lishunzhi发表于2009-10-21 00:11
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
置换群,但建环是重点0
回复 zebra发表于2009-10-03 09:48
#include <iostream>
#include <cassert>
using namespace std;
long N,seq[50001],p=1;
class
{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2)
{
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2)
return true;
return false;
}
public:
bool AddE(long v1,long v2)
{
if(isnbr(v1,v2))
return true;
else
if(nbr[v1][0]==2||nbr[v2][0]==2)
return false;
else
{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i)
{
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++)
{
if(!flag[nbr[i][j]])
{
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve()
{
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N;
b=seq[i]-(N+1-i);
if(b<0) b+=N;
if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main()
{
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++)
{
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2))
{
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
system("pause");
return 0;
}0
回复 -117-Join发表于2009-09-18 21:29
哪位大牛帮忙看看我错哪里了
它只得90分
program fire;
type
arr=record
l,r:longint;
end;
var
num:array[1..50000]of longint;
a:array[1..50000]of arr;
b:array[1..50000]of longint;
i,k,j,n:longint;
begin
readln(n);
for i:=1 to n do
readln(a[i].l,a[i].r);
b[1]:=1;
b[n]:=a[1].l;
if a[b[n]].l=b[1]then b[n-1]:=a[b[n]].r
else b[n-1]:=a[b[n]].l;
i:=n-1;
b[2]:=a[1].r;
j:=2;
while j<=i do
begin
if b<>a[b[i]].l then b:=a[b[i]].l
else b:=a[b[i]].r;
dec(i);
if b[j-1]<>a[b[j]].r then b[j+1]:=a[b[j]].r
else b[j+1]:=a[b[j]].l;
inc(j);
end;
for i:=2 to n-1 do
if(b<>a[b[i]].r)and(b<>a[b[i]].l)or(b<>a[b[i]].r)and(b<>a[b[i]].l)then
begin
write(-1);
halt
end;
if(b[n]<>a[b[1]].l)and(b[n]<>a[b[1]].r)or(b[2]<>a[b[1]].l)and(b[2]<>a[b[1]].r)or(b[1]<>a[b[n]].l)and(b[1]<>a[b[n]].r)or(b[n-1]<>a[b[n]].l)and(b[n-1]<>a[b[n]].r)then
begin
write(-1);
halt
end;
num[0]:=0;
for i:=1 to n do
begin
a[b[i]].l:=i;
num[i]:=0;
end;
for i:=1 to n do
if a[i].l-i>=0 then inc(num[a[i].l-i])
else inc(num[a[i].l-i+n]);
j:=0;
for i:=0 to n do
if num[i]>j then j:=num[i];
write(n-j);
end.
写的有点长0
回复 fs302发表于2009-09-17 20:13
分析:学一个好思想:正难则反!由顺序到乱序我们很难快速找到,但是我们知道如何从乱序变为顺序!解决本题利用了组合数学中置换群的思想。从第一个人处断开,将圆环的问题转化为序列的问题。如果可以,求出目标序列。求出目标序列复杂度O(n).
求出目标序列右移0至n-1位置时,不需要移动的人数。将目标序列反转,再求出目标序列右移0至n-1位置时,不需要移动的人数。求不需要移动的人数最大等价于求需要移动的人数最小。复杂度O(n)。
更详细的说:
引进“相对有序”这个概念,当两个人满足C[j]-C[i]==j-i时,两个相对有序。
题目要求最小的总代价,但是我们可以考虑倒过来想,要求最小的总代价亦即求最多有多少人不用移动,亦即相对有序。
然后我们引进一个辅助变量T=C-I,{C-I>=0},T=C[i]-I+N,{C[i]-I<0},那么这个T[i]有什么意义呢?我们知道初始状态的编号是1-N,而目标状态是C[1]-C[N],那么C-I便是从目标状态到初始状态顺时针所要移动的距离,那么如果那么T值相等的两个同学则是相对有序的,亦即不用移动,我们只要找出最大的T然后N-Max(T)就是得到的结果,但是这样还不够,因为刚刚那样只是顺时针所要移动的距离,我们还要计算逆时针的到的结果,从顺时针和逆时针中找到最大的T,然后N-Max(T)才能够是正确结果.0
回复 maxint64发表于2009-09-01 21:33
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
先是物理大发了——以为 b1,b2...bm是连续的
看了牛们的题解 一次ac :)0
回复 柔情使者发表于2009-08-20 15:44
第一遍做的时候没有看题解,自己测了好几遍总是60分,看了n多大牛的解释才恍然大悟,竟然要正反两遍!!!唉,幸亏咱有测试数据,否则我可就惨了...
O(n)的求目标队列算法,都说是冒泡排序,我没看出来,倒是有点像。0
回复 maxiem发表于2009-08-18 20:55
物理自重啊,嘿嘿。
注意要正反两遍哦~
9MS?
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 9ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:9ms
(好像那个冒泡是口胡,大家不要被那个蒙了
program fire;
var
st:array [1..50000,1..2] of longint;
k,final:array [0..50000] of longint;
ex:array [1..50000] of boolean;
p,max,i,n:longint;
begin
fillchar (st,sizeof(st),0);
fillchar (ex,sizeof(ex),0);
fillchar (final,sizeof(final),0);
fillchar (k,sizeof(k),0);
readln (n);
for i:=1 to n do readln (st,st);
final[1]:=1;p:=2;ex[1]:=true;
for i:=1 to n do begin
if ex[st[final[i],1]]=false then begin
final[p]:=st[final[i],1];
ex[st[final[i],1]]:=true;
inc(p);
end
else if ex[st[final[i],2]]=false then begin
final[p]:=st[final[i],2];
ex[st[final[i],2]]:=true;
inc(p);
end;
end;
if p-1<>n then begin
writeln (-1);
halt;
end;
max:=0;
for i:=1 to n do if final[i]>=i then inc(k[final[i]-i]) else inc(k[n-i+final[i]]);
for i:=0 to n-1 do if k[i]>max then max:=k[i];
fillchar (k,sizeof(k),0);
for i:=n downto 1 do if final[i]>=n-i+1 then inc(k[final[i]-n+i-1]) else inc(k[final[i]+i-1]);
for i:=0 to n -1 do if k[i]>max then max:=k[i];
writeln (n-max);
end.0
回复 suning发表于2009-08-14 09:43
啊呜~
一年前误解了题意~
一年后理解了题意~
然后就是1次美妙的ACPS:[误]解[理]解~~~[物理]?
0
回复 fengwuliu发表于2009-08-13 17:20
lgxcgd说的太对了!太感谢了55550
回复 Matt发表于2009-08-11 22:28
NOIP也会考高等数学...由于原图是环,所以置换群可表示为一次循环。作差是个好方法。
但求冒泡排序是怎么作的
0
回复 3830372发表于2009-08-11 21:28
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1504人
提交 4282次
通过率 35%
难度 3提交 讨论 题解 状态
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 尖端才子发表于2009-08-11 11:14
纪念一下……第1500个AC……Flag Accepted
题号 P1008
类型(?) 模拟
通过 1500人
提交 4274次
通过率 35%
难度 3编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 SecretAgent发表于2009-08-10 14:02
置换群是正解编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 yangbei发表于2009-08-07 14:57
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 338ms
├ 测试数据 05:答案正确... 322ms
├ 测试数据 06:答案正确... 306ms
├ 测试数据 07:答案正确... 338ms
├ 测试数据 08:答案正确... 338ms
├ 测试数据 09:答案正确... 322ms├ 测试数据 10:答案正确... 306ms
Accepted 有效得分:100 有效耗时:2270ms
算镜像时偷了点懒,不过也算一遍AC了
0
回复 ja_son发表于2009-08-06 15:44
a:拆环成队,寻求目标队列。
b:b1,b2...bm不是连续的,而且是任意的。只要有成立目标队列,与原来的队列相匹配就可以知道有多少(设为n个)需要移动位置,则代价就是n。
c:目标队列有多种情况,可以反转,也可以左右移动。0
回复 1s发表于2009-08-03 17:56
如对本题有疑问可以参看我的题解:
http://xujieqi.blog.hexun.com/35722312_d.html0
回复 DMKaplony发表于2009-07-30 15:15
当时的时间限制好像是2s。。有个题解说把1定为第一项然后进行冒泡排序。。不过这里是1s 啊。。。也行只有置换群了吧。0
回复 xusc_2009发表于2009-07-28 14:30
看不懂,只好搁浅
什么时候想清楚了再做0
回复 董发表于2009-07-24 19:11
program p1008;
var i,n,k,j,sum1,sum2,ans,max:longint;
a,b,w,d,c:array[0..50005] of longint;begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
w[1]:=1; w[2]:=a[w[1]];
k:=1;repeat
inc(k);
if w[k-1]=a[w[k]] then w[k+1]:=b[w[k]]
else if w[k-1]=b[w[k]] then w[k+1]:=a[w[k]]
else begin
writeln(-1);
exit;
end;
until k=n;
if w[n+1]<>w[1] then
begin
writeln(-1);
exit;
end;for i:=1 to n do
begin
a[i]:=w[i]-i;
b[i]:=w[n-i+1]-i;
if a[i]<0 then a[i]:=a[i]+n;
if b[i]<0 then b[i]:=b[i]+n;
inc(c[a[i]]);
inc(d[b[i]]);
end;
for i:=0 to n-1 do
begin
if ans<c[i] then ans:=c[i];
if ans<d[i] then ans:=d[i];
end;
writeln(n-ans);
end.0
回复 我飞发表于2009-07-23 21:00
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 93狒狒发表于2009-07-23 20:59
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
秒杀......
0
回复 fjxmlhx发表于2009-07-22 13:15
置换群,做2n次,顺时针和逆时针.
对于一个置换,最小操作费用是所有循环长度的和.因此实际上是找出2n个置换中哪个置换循环长度为1的数量最多.0
回复 340508965发表于2009-07-21 15:01
⊙﹏⊙b汗
不知道的以为这是数学竞赛......
...
我的数论与图论可以说脑袋里空白一片.........
怎么办,我的竞赛啊
........算了 看了题解 大家写的
总算弄懂这道题了
先前以为b1,b2,b3..bm是连续的
没想到是任意的!!!!!!!!!诶 叹悲歌未切 为撼奈何编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
总算AC了
program p1008;
var i,n,k,j,sum1,sum2,ans,max:longint;
a,b,w,d,c:array[0..50005] of longint;begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
w[1]:=1; w[2]:=a[w[1]];
k:=1;repeat
inc(k);
if w[k-1]=a[w[k]] then w[k+1]:=b[w[k]]
else if w[k-1]=b[w[k]] then w[k+1]:=a[w[k]]
else begin
writeln(-1);
exit;
end;
until k=n;
if w[n+1]<>w[1] then
begin
writeln(-1);
exit;
end;for i:=1 to n do
begin
a[i]:=w[i]-i;
b[i]:=w[n-i+1]-i;
if a[i]<0 then a[i]:=a[i]+n;
if b[i]<0 then b[i]:=b[i]+n;
inc(c[a[i]]);
inc(d[b[i]]);
end;
for i:=0 to n-1 do
begin
if ans<c[i] then ans:=c[i];
if ans<d[i] then ans:=d[i];
end;
writeln(n-ans);
end.0
回复 zsy90943发表于2009-07-18 00:51
构造巧妙、、看来还是要学好数论和图论额、、、、0
回复 POM无敌牛B发表于2009-07-16 11:47
编译通过...
├ 测试数据 01:运行超时...
├ 测试数据 02:运行超时...
├ 测试数据 03:运行超时...
├ 测试数据 04:运行超时...
├ 测试数据 05:运行超时...
├ 测试数据 06:运行超时...
├ 测试数据 07:运行超时...
├ 测试数据 08:运行超时...
├ 测试数据 09:运行超时...├ 测试数据 10:运行超时...
Unaccepted 有效得分:0 有效耗时:0ms
无奈 哪位哥哥救救我0
回复 yxy发表于2009-06-16 18:16
把置换解释成度为2图,真有才.
求出序列,正反分别做一次差就行了.0
回复 sxpeter发表于2009-06-14 16:56
讲建环吧。数组w表示环,我用的是一种类似并查集的方法。
begin
read(n);
for i:=1 to n do read(a[i],b[i]);
t:=2;w[1]:=1;w[2]:=a[1];
while true do begin
if a[w[t]]<>w[t-1]then w[t+1]:=a[w[t]]//是否在左边
else if b[w[t]]<>w[t-1]then w[t+1]:=b[w[t]]//是否在右边
else begin writeln(-1);halt;end;//失败判断
inc(t);
if t>n then break;
end;
if w[n+1]<>w[1]then begin writeln(-1);halt;end;//本句一定要加!!!!!!
end.0
回复 lgxcgd发表于2009-05-17 20:24
首先把这个圈看做一个图,每个同学看做一个顶点。因为要形成环,所以每个顶点的度必须为2。如果存在度数不为2的顶点,那么整个图无法构成一个环,即“无论怎么调整都不能符合每个同学的愿望”输出-1。
如果是一个环,那么就遍历图,生成以第1个顶点为开头的序列。现在就要求出最小移动的代价。
在理解题意所述的调整方式中,要注意实际上就是把M个在错误位置上的人移动到正确的位置上,代价为M。一次下令移动即可。
假如生成的目标序列为1,5,3,2,4。我们现在就需要比较它和初始状态1,2,3,4,5,看有几个人离开了原来的位置。但这个序列实际代表的是一个环,而且方向正反有两种,就需要把初始序列正反分别转N次,和得到的序列比较,看其中最少有几个位置上的人编号不相同,就得到了我们要求的最小代价。
上述方法有大量冗余。但可以发现转来转去不管怎么转,任意两个人之间的相对位置关系在这过程中都不会变。于是想到做差,如果差小于0则加上N。
1 5 3 2 4
- 1 2 3 4 5
0 3 0 3 4
这表示序列1,5,3,2,4不转动时1,3两个人在原来的位置上,转动3个位置后5和2两个人在原来的位置上,转动4个位置后只有4一个人会在原来的位置上。这就是说,1,5,3,2,4与1,2,3,4,5在旋转后最多有2个位置上的人编号相同,即最少有3个位置上的人编号不相同。同理要反转再求一次。记录每个不同的差值的个数,取其最大值P,即不调换次数最大的。结果N-P就是调换次数最小的。
0
回复 src250发表于2009-05-14 08:27
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
切记:重新构图时一定要对数组清空!我的第一次只有50分,就是这个原因!
0
回复 love19960108发表于2009-04-26 17:59
这题可以用C++这样做么??
#include <iostream>
#include <cassert>
using namespace std;
long N,seq[50001],p=1;
class{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2){
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2) return true;
return false;
}
public:
bool AddE(long v1,long v2){
if(isnbr(v1,v2)) return true;
else if(nbr[v1][0]==2||nbr[v2][0]==2) return false;
else{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i){
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++){
if(!flag[nbr[i][j]]){
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve(){
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N;
b=seq[i]-(N+1-i);
if(b<0) b+=N;
if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main(){
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++){
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2)){
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
return 0;
}0
回复 voyagec2发表于2009-03-18 15:53
难理解,不过算法很精妙0
回复 pRoevollove发表于2009-02-25 23:49
天,把(p[i]-i+n)mod n理所当然地打成了abs(p[i]-i)
结果一直50分……还一直以为自己构造错了……ps 我可以过楼下的范例哦
0
回复 ufo172849z发表于2009-01-24 23:05
ms楼下的程序不能处理这种反例(测试数据还是不够强啊)
6
2 3
1 3
1 2
5 6
4 6
4 5
应该输出-1的吧?因为是两个环var a,b:array[0..50000]of longint;
c:array[0..50000,1..2]of longint;
d:array[0..50000]of boolean;
i,j,k,m,n,max:longint;
can:boolean;begin
readln(n);
for i:=1 to n do
readln(c,c);
b[0]:=c[1,1]; b[n]:=c[1,1];
fillchar(d,sizeof(d),0);
k:=1;
can:=true;
for i:=1 to n-1 do
begin
if d[k] then can:=false;
b[i]:=k; d[k]:=true;
if b=c[k,1] then k:=c[k,2]
else if b=c[k,2] then k:=c[k,1]
else can:=false;
if not can then break;
end;
if can then
if b[n]<>k then can:=false;
if can then
begin
max:=-1;
fillchar(a,sizeof(a),0);
for i:=1 to n do
inc(a[(b[i]-i+n) mod n]);
for i:=0 to n-1 do
if a[i]>max then max:=a[i];
fillchar(a,sizeof(a),0);
for i:=1 to n do
inc(a[(b[n-i+1]-i+n)mod n]);
for i:=1 to n-1 do
if a[i]>max then max:=a[i];
writeln(n-max);
end
else
writeln(-1);
end.0
回复 tangdongjian发表于2009-01-23 22:17
我在做镜像时把原先max直接覆盖上了,注意0
回复 永恒888发表于2009-10-26 22:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 tangkunjie发表于2009-06-04 19:50
挺烦人的题目0
回复 ykspeter发表于2008-11-13 20:32
program fire(input,output);
var
n,i,j,k,max,v:longint;
a:array[0..100000,1..2] of longint;
b,c:array[0..100000] of longint;
begin
readln(n);
for i:=1 to n do readln(a,a);
for i:=1 to n do
begin
k:=0;
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if (k=4) or (k=3)
then begin
writeln('-1');
exit
end
end;
b[1]:=1;i:=2;k:=a[1,1];j:=1;
repeat
b[i]:=k;
inc(i);
v:=k;
if a[k,1]<>j
then k:=a[k,1]
else k:=a[k,2];
j:=v;
until i=n+1;
fillchar(c,sizeof(c),0);
for i:=1 to n do inc(c[(b[i]-i+n)mod n]);
for i:=0 to n-1 do
if c[i]>max
then max:=c[i];
fillchar(c,sizeof(c),0);max:=0;
for i:=1 to n do inc(c[(b[n-i+1]-i+n)mod n]);
for i:=n-1 downto 0 do
if c[i]>max
then max:=c[i];
writeln(n-max);
end.0
回复 getuojian发表于2008-11-10 13:38
#include<stdio.h>
#include<memory.h>const int maxn=50010;
int n;
int f[maxn][2];
int goal[maxn];
int ans=maxn;
int hash[maxn];bool SET_ORI(){
bool flag[maxn];
memset(flag, true, sizeof(flag));
goal[1]=1; flag[1]=false;
for (int i=1; i<=n-1; i++){
if (flag[f[goal[i]][0]]){
goal=f[goal[i]][0];
flag[f[goal[i]][0]]=false;
continue;
}
if (flag[f[goal[i]][1]]){
goal=f[goal[i]][1];
flag[f[goal[i]][1]]=false;
continue;
}
return false;
}
if ((goal[n]!=f[1][0]) && (goal[n]!=f[1][1]))
return false;
return true;
}
int SWAP(int i, int j){
int t=goal[i];
goal[i]=goal[j];
goal[j]=t;
return 0;
}int min(int i, int j){
return i>j?j:i;
}
int HASH(){
for(int i=1; i<=n; i++)
hash[i]=goal[i]-i+n;
return 0;
}int CALC(){
int temp[maxn*2], back=0;
memset(temp, 0, sizeof(temp));
for (int i=1; i<=n; i++)
temp[hash[i]%n]++;
for (int i=1; i<=2*n-1; i++)
if (temp[i] > back)
back=temp[i];
return back;
}int main(){
freopen("fire.in", "r", stdin);
freopen("fire.out", "w", stdout);
scanf("%d", &n);
for (int i=1; i<=n; i++)
scanf("%d %d", &f[i][0], &f[i][1]);
if (!SET_ORI()){
printf("-1");
return 0;
}
//forward
HASH();
ans=min(ans, n-CALC());
//backward
for (int i=1; i<=n/2; i++)
SWAP(i,n-i+1);
HASH();
ans=min(ans, n-CALC());printf("%d", ans);
return 0;
}0
回复 IVORY发表于2008-11-06 10:46
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
CHEAT的...
0
回复 storey p发表于2008-11-05 14:19
回447389831:
exit换成halt0
回复 FenXy发表于2008-11-04 08:28
艺术p2450
回复 hlq发表于2008-11-01 14:31
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms求不在位置上的人数
a【i】 第i位上的同学编号
for i:=1 to n do
begin
inc(b[(a[i]-i+n) mod n])
end;
max:=0;
for i:=0 to n-1 do
if b[i]>max then max:=b[i];
fillchar(b,sizeof(b),0);
for i:=1 to n do
begin
inc(b[(a[i]-(n-i+1)+n)mod n]);//对称
end;
for i:=0 to n-1 do
if b[i]>max then max:=b[i];0
回复 Will~骷髅发表于2008-10-30 21:37
编译通过...
├ 测试数据 01:运行超时...
├ 测试数据 02:运行超时...
├ 测试数据 03:运行时错误...|错误号: -1073741819
├ 测试数据 04:运行时错误...|错误号: -1073741819
├ 测试数据 05:运行时错误...|错误号: -1073741819
├ 测试数据 06:运行时错误...|错误号: -1073741819
├ 测试数据 07:运行时错误...|错误号: -1073741819
├ 测试数据 08:运行时错误...|错误号: -1073741819
├ 测试数据 09:运行时错误...|错误号: -1073741819├ 测试数据 10:运行时错误...|错误号: -1073741819
Unaccepted 有效得分:0 有效耗时:0ms
怎么会这样???
0
回复 悲伤逆流成河发表于2008-10-28 22:13
#include <iostream>
#include <fstream>
using namespace std ;int hash[50001];
int n , i , j , t , maxs(0) ;inline void HASH ( int e[] )
{
for ( i = 1 ; i <= n ; i++ )
{
e[i] -= i ;
if ( e[i] < 0 ) e[i] += n ;
hash[e[i]]++ ;
}
for ( i = 0 ; i < 50001 ; i++ )
if ( maxs < hash[i] ) maxs = hash[i] ;
}int main(){
ifstream fin ("fire.in") ;
ofstream fout ("fire.out") ;fin >> n ;
int e[n+1] , h[n+1][2] , e2[n+1];
bool f[n+1] ;
for ( i = 1 ; i <= n ; i++ )
{
f[i] = false ;
fin >> h[i][0] >> h[i][1] ;
}
e[1] = 1 ;
f[1] = true ;
for ( i = 2 ; i <= n ; i++ )
{
if ( e < 0 ) { fout << -1 << endl ; exit(0) ; }
if ( !f [ h[ e ][0] ] ) e[i] = h[ e ][0] ;
if ( !f [ h[ e ][1] ] ) e[i] = h[ e ][1] ;
f[ e[i] ] = true ;
}
for ( i = 1 , j = n ; i <= n ; i++,j-- ) e2[j] = e[i] ;
HASH ( e ) ;
memset ( hash , 0 , sizeof ( hash ) ) ;
HASH ( e2 ) ;
fout << n - maxs << endl ;
}0
回复 evelynhe发表于2008-10-26 16:31
“置换群思想...今天刚明白...先构造新数列(要构造两次,否则只有70分),然后向右计算相对位置差,然后累加记录数组,然后用N减去相对位置差累加值最大的,就是答案... ”
这是真的
0
回复 true1023发表于2008-10-25 09:32
置换群的基本概念
利用原序列和目标序列每个元素的绝对位置差来求出原序列每个元素对于目标序列的相对位置,找相对位置相同的最多的元素数,用总元素数减去它即为结果。0
回复 447389831发表于2008-10-21 09:45
program fire(input,output);
var
n,i,j,k,max,v:longint;
a:array[0..100000,1..2] of longint;
b,c:array[0..100000] of longint;
begin
readln(n);
for i:=1 to n do readln(a,a);
for i:=1 to n do
begin
k:=0;
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if (k=4) or (k=3)
then begin
writeln('-1');
exit
end
end;
b[1]:=1;i:=2;k:=a[1,1];j:=1;
repeat
b[i]:=k;
inc(i);
v:=k;
if a[k,1]<>j
then k:=a[k,1]
else k:=a[k,2];
j:=v;
until i=n+1;
fillchar(c,sizeof(c),0);
for i:=1 to n do inc(c[(b[i]-i+n)mod n]);
for i:=0 to n-1 do
if c[i]>max
then max:=c[i];
fillchar(c,sizeof(c),0);max:=0;
for i:=1 to n do inc(c[(b[n-i+1]-i+n)mod n]);
for i:=n-1 downto 0 do
if c[i]>max
then max:=c[i];
writeln(n-max);
end.
90 分,牛人门帮看下把0
回复 cnfnje1发表于2008-10-17 18:12
置换群.....是什么?
readln(n);
for i:=1 to n do readln(a[i],b[i]);
c[1]:=1; c[2]:=a[1];
for i:=3 to n do if c=a[c] then c[i]:=b[c]
else if c=b[c] then c[i]:=a[c]
else begin writeln(-1); halt end;
if c[n]<>b[1] then begin writeln(-1); halt end;
fillchar(d,sizeof(d),0);
for i:=1 to n do inc(d[(c[i]-i+n)mod n]);
for i:=0 to n-1 do if d[i]>m then m:=d[i];
fillchar(d,sizeof(d),0);
for i:=1 to n do inc(d[(c[i]+i-1)mod n]);
for i:=0 to n-1 do if d[i]>m then m:=d[i];
writeln(n-m);
是么?0
回复 lyrics发表于2008-10-12 19:55
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
技巧性比较强吧,楼下不必构造2次,计算时从头至尾算一次,再倒过来算一次就行了
0
回复 LV.唱响发表于2008-10-05 08:38
置换群思想...今天刚明白...先构造新数列(要构造两次,否则只有70分),然后向右计算相对位置差,然后累加记录数组,然后用N减去相对位置差累加值最大的,就是答案...
0
回复 宇智波带波斯猫发表于2008-10-05 08:33
Flag Accepted
题号 P1008
类型(?) 其它
通过 1065人
提交 3000次
通过率 35%
难度 3第3000个提交的
0
回复 鸳鸯羡发表于2008-09-28 18:19
#include <iostream>
using namespace std ;int hash[50001];
int n , i , j , t , maxs(0) ;inline void HASH ( int e[] )
{
for ( i = 1 ; i <= n ; i++ )
{
e[i] -= i ;
if ( e[i] < 0 ) e[i] += n ;
hash[e[i]]++ ;
}
for ( i = 0 ; i < 50001 ; i++ )
if ( maxs < hash[i] ) maxs = hash[i] ;
}int main(){
cin >> n ;
int e[n+1] , h[n+1][2] , e2[n+1];
bool f[n+1] ;
for ( i = 1 ; i <= n ; i++ )
{
f[i] = false ;
cin >> h[i][0] >> h[i][1] ;
}
e[1] = 1 ;
f[1] = true ;
for ( i = 2 ; i <= n ; i++ )
{
if ( e < 0 ) { cout << -1 << endl ; exit(0) ; }
if ( !f [ h[ e ][0] ] ) e[i] = h[ e ][0] ;
if ( !f [ h[ e ][1] ] ) e[i] = h[ e ][1] ;
f[ e[i] ] = true ;
}
for ( i = 1 , j = n ; i <= n ; i++,j-- ) e2[j] = e[i] ;
HASH ( e ) ;
memset ( hash , 0 , sizeof ( hash ) ) ;
HASH ( e2 ) ;
cout << n - maxs << endl ;
}80分
0
回复 月光疾风发表于2008-09-25 13:03
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
纪念我第200次提交!过第79题。。。。0
回复 ghostplant发表于2008-09-20 19:48
#include <iostream>
#include <fstream>
#include <cassert>
using namespace std;
long N,seq[50001],p=1;
class{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2){
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2) return true;
return false;
}
public:
bool AddE(long v1,long v2){
if(isnbr(v1,v2)) return true;
else if(nbr[v1][0]==2||nbr[v2][0]==2) return false;
else{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i){
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++){
if(!flag[nbr[i][j]]){
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve(void){
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N;
b=seq[i]-(N+1-i);
if(b<0) b+=N;
if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main(){
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++){
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2)){
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
return 0;
}0
回复 zzh19950802发表于2008-09-17 19:29
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案错误... ├ 标准行输出
├ 错误行输出
├ 测试数据 05:答案错误... ├ 标准行输出
├ 错误行输出
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 462ms
├ 测试数据 08:答案正确... 369ms
├ 测试数据 09:答案正确... 384ms
├ 测试数据 10:答案错误...程序输出比正确答案长
为什么我的程序不对?
#include <iostream>
using namespace std;
#define MAXN 50000
int man[MAXN+2][2];
int cercle[MAXN+2]={0,1};
int used[MAXN+2]={0};
int reduce[2][MAXN+2]={0};
int n;
int main()
{
long i,p,q=1,t;
int max=0;
cin>>n;
for (i=1;i<=n;i++) cin>>man[i][0]>>man[i][1];
p=man[q][1];
for (i=2;i<=n+1;i++)
{
if (man[q][1]==p)
{
p=q;
q=man[q][0];
}
else
{
if(man[q][0]!=p) break;
p=q;
q=man[q][1];
}
if(used[q]) break;
else used[q]=1;
cercle[i]=q;
}
if (i<=n+1) cout<<-1;
else
{
for (i=1;i<=n;i++)
{
if((t=cercle[i]-i)<0) t+=n;
reduce[0][t]++;
if (reduce[0][t]>max) max=reduce[0][t];
if ((t=cercle[i]-n+i-1)<0) t+=n;
if (reduce[1][t]>max) max=reduce[1][t];
}
cout<<n-max;
}
return 0;
}0
回复 liaorc发表于2008-09-16 17:56
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 cxy450090074发表于2008-09-04 13:34
oh no0
回复 Lost.G发表于2008-08-22 15:49
我在想``怎么样才能不看错这题呢0
回复 bonism发表于2008-08-14 21:30
时间复杂度O(N)。。。原来我一直把题意理解错。。。囧!!。。
关于“置换群”,请看LRJ的《算法艺术与信息学竞赛》P245那一小节,还是比较好理解的。
0
回复 lemon_cn发表于2008-08-08 15:55
热烈庆祝用pascal AC的第二题~
p.s.我是C++的~~0
回复 oipn4e2发表于2008-08-05 21:36
解决效率不高,但AC了。0
回复 notblack发表于2008-08-01 09:17
用距离来分类,统计在原位的最大人数,奇怪的是
b[1]:=1;
b[2]:=a[1,1];
b[n]:=a[1,2];建环的时候,上面的改成
b[1]:=1;
b[2]:=a[1,2];
b[n]:=a[1,1];最后一个点却过不了,太奇怪了.
0
回复 332404521发表于2008-07-14 13:53
对于初三刚刚中考完的我,要理解这题的意思是万万不能的。。。
看题解我知道了应该怎么做,但那不是我的,所以不做了。。。
哪天能证明出来那啥再来做0
回复 Sheeta发表于2007-11-14 15:45
好简单啊
直接贪啊
(P.S.置换群?什么东东...)0
回复 mingyueyucai发表于2007-11-09 21:22
我代码写了老长老长,结果还是只过了8个点,有没有搞错?
我想请问一下,我和大家的一样,先排列出目标状态.然后确定初始状态时使得最多的人在目标位置上,然后交换.但是得到的答案总是偏大一点.
然后我又把所有可以使最多的人在原位目标位置上的可能都尝试了一编(包括正反两个目标状态),结果还是只能过8个点,有2个点死都过不了!
我的算法有什么问题吗?0
回复 luanjiyang发表于2007-11-08 08:44
很委琐的说 我提交了8遍。。
0→0→10→10→10→10→70→AC- -||
0
回复 lonelycorn发表于2007-11-05 23:31
数论……好底歇的东西。0
回复 gamejifan发表于2007-11-04 11:15
这题的叙述,让我误会了一年多。tzkq……3q..要早知道是这种意思早就ac了这题。。显然没什么大意思,看过组合数学或者学过群论的都懂。。ms跟polya计数法那个循环的意思。。写的时候竟然因为交换的时候写错一个字母wa。我汗。
0
回复 Alexandria发表于2007-11-01 13:33
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
好强大的题啊,不看题解还真不会!
0
回复 clfhaha1234发表于2007-10-30 18:09
请问什么是置换群啊?可以讲讲吗?………………0
回复 rleepas发表于2007-10-30 13:18
楼下都是正解?
......0
回复 Ice_Msk发表于2007-10-18 20:35
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
什么是置换群?不知道。。。照样过。。。。
0
回复 junlonely发表于2007-10-18 20:13
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 江南不才发表于2007-10-11 16:19
排序法这里会超时~~~~~
比赛的时间是2S~~
这里是1S~~
(_)0
回复 秒杀群众发表于2007-10-10 17:05
居然是置换群。。。
对了。。。什么是置换群...
上网查啊!!!0
回复 southstarj1发表于2007-10-02 18:50
思想:
置换群。(相关知识自己查)
对于一组数据,按各人的意愿排出一个序列,
如果无法排出,就输出-1。
再将环状序列变成链状,则这个目标序列为一个置换群,
与原序列(按1到n的一列)满足:
交换的最少人数等于目标序列与原序列不重合的人数。
因为总共有2n个目标序列(正反各n种),都算一遍就行了。步骤:
1. 读入数据;
2. 构造一个目标序列;
3. 统计该序列中元素位置与该元素在原序列位置的差值(同一方向)为i{i ∈ [0, n)}的元素个数;
4. 将该序列的反序统计一遍;
5. 从这些数据中选取一个最大的值max;
6. 输出n - max;注意:
构造目标序列时判断能否构造的条件;
统计一次差值的复杂度是O(n);
统计差值的目的是求与原序列最多的重合人数;0
回复 wangjin5发表于2007-09-19 22:38
好经典的题奥
确实有难度0
回复 the_melody发表于2007-09-03 17:58
Accepted 有效得分:100 有效耗时:0ms
好经典的题奥0
回复 richardxx发表于2007-08-22 17:36
下面程序是错的,不好意思,弄错地方了....0
回复 sm-star发表于2007-08-21 15:18
题目所求就是每次进行连续交换的人数总和,这样,一个看似复杂的题目就变的异常的简单了!0
回复 wasyyyy发表于2007-08-11 02:05
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
HOHO~~~看讨论的时候看到有人提到‘置换群’这个东西,突然想起来我刚买的一本组合数学上有这么一块东西,就拿过来看了。。。。
然后就出现上面的东西了。。。。置换群,本来想求轮换的,发现轮换比较多,还是找不参与交换的比较好记。。。。优化的方法。。。我看了下好象不只一个人讲过了。。。而且似乎我跟他们的都一样(没仔细看)所以就不说了。。。效率是O(n)的。。不用建环。
0
回复 angieqiu发表于2007-08-10 22:49
怎么判断建环失败啊?我的程序虽然AC但总觉得方法很傻0
回复 梦ぁ逍遥发表于2007-07-17 13:45
想到了用t[i]=b[i]-i表示环
却没想到镜像..十分感谢visister
让我从90分中挣扎出来...0
回复 visister发表于2007-06-01 00:12
首先明显地可以知道我们需要对于目标状态建立出一个环。如果无法建立这个环,那么结果一定是-1,当建立好环以后可以知道最小移动代价一定等于最少的不在目标位置上的人数。那么我们可以对目标环进行顺时针旋转1~n-1之中任意一个,答案就一定等于旋转中的不在自己位置上的人数最少的那样的环的状态。但是对于50000的数据,我们如果要将环旋转1~n-1次,那么总共加上判断不在自己位置上的人数时间复杂度为O(n^2),显然在限定时间内是无法出解的。因此我们进行逆向思维:不在自己位置上最少的人数就一定会等于总人数减去在自己位置上最多的人数(仔细想想),那么我们就将该问题转化为了求在自己的位置上最多的人数,这样一来,我们对初始目标环中每一个位置进行判断需要旋转多少次可以回到自己位置上,每一个人的选择都将映射到[0..n-1]的数组中,选取当中最大的情况就为所求,但是考虑到环可以反转,那么我们还需要将环再求一次镜像,就可以得到初始目标需要旋转多少次可以得到在自己位置上最多的人数的环的状态,最后通过总的人数减去它即为问题所求,时间复杂度为O(n);0
回复 pyh119发表于2006-11-16 20:11
哪个人不小心失火了找我啊!!!PS:我是安徽省芜湖市119接线员....
0
回复 maomingming发表于2006-11-06 18:40
考虑旋转后最多可能重合的情况,另要注意圈可以反过来0
回复 qian5发表于2006-09-30 21:35
直接输出‘-1’有一个点过0
回复 BambooLeaf发表于2006-09-26 18:17
见过的最牛最简单的方法……
将此题转换为冒泡排序,记录下所有交换的次数和两数间的距离,加上就行了……—__—|||
具体是这样的,我们反向思维,本来是要求一个有序数列求出成为无序数列的代价,现在我们把无序数列(即目标数列)进行冒泡排序,然后……就是这样……
看完之后,偶巨汗……0
回复 xcjzj发表于2006-09-26 17:18
每组数据确定两组相对位置关系,并且这两组互为镜像。
对于某一种排列方式,不在需要位置上的人数即为当前状态到目标状态的最小代价。
先找出其中一种排列方式。由于目标状态可以通过旋转而使得部分人的变化次数减少,所以找出每个人通过某一固定方向旋转到达目标位置的旋转次数。找到某一次数,使得拥有这个次数的人数最多。那么,通过旋转这一最多人拥有的次数,即可使得尽可能多的人不通过交换直接到达目标位置。于是,不拥有这一旋转次数的人数即为这一状态下的最小代价。
然后,用现在的目标状态找出其镜像状态,并且用上述方法再找一遍最小代价,与前面的结果比较,较小值即为答案。
另外,题目中会出现一些无解的情况:
1.某个人被“要”的次数多于两次,也就是说有多于两个的人想要与他(她)邻座,那么无解。
2.根据要求得出的目标状态为多于一个的环,也无解。0
回复 东邪歪刀发表于2006-07-28 17:27
提交了若干次……残念……0
回复 sugar发表于2006-07-28 16:26
这题比赛时真有人ac?
真不好想
为什么得开longint啊?0
回复 晶星发表于2006-07-25 13:29
排列本质不同的只有二种 正着和反着的
检验几个人不在位置上用数学方法:)模拟法超时的0
回复 tzkq发表于2006-07-23 04:37
注意别误解题意 b1,b2....bm并不指连续位置上的数0
回复 Coldwings发表于2006-01-26 09:21
可以用群论证明:如果有k个人不在自己的位置上,那么要且仅要k的代价,即可使这些人归位剩下的..很简单了吧...
0
回复 lemon_cn发表于2008-08-08 15:55
热烈庆祝用pascal AC的第二题~
p.s.我是C++的~~ -
-12015-07-05 11:02:04@
0
回复 yingjiangyu发表于2015-02-15 21:55
打‘Wrong!’有50分。。0
回复 东大微雕发表于2015-02-07 15:20
这道题真是太好了。奇妙无穷。
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
int a[50005];
int size;
void go(){
int i, j;
int ans = 0;
int dis[50005];
memset(dis, 0, sizeof(dis));
for (i = 1; i <= size; i++){
int d = (a[i] - i + size) % size;
dis[d]++;
}
for (i = 0; i < size; i++){
if (ans < dis[i])
ans = dis[i];
}
memset(dis, 0, sizeof(dis));
for (i = 1; i <= size; i++){
int d = (a[size+1-i]-i+size) % size;
dis[d]++;
}
for (i = 0; i < size; i++){
if (ans < dis[i])ans = dis[i];
}
cout << size-ans << endl;
}
int main(){
freopen("in.txt", "r", stdin);
int neibor[50005][2];
int i;
cin >> size;
for (i = 1; i <= size; i++){
scanf("%d%d",&neibor[i][0],& neibor[i][1]);
}
bool used[50005];
memset(used, 0, sizeof(used));
a[1] = 1;
used[1] = true;
for (i = 2; i <= size; i++){
int last = a[i - 1];
if (!used[neibor[last][0]]){
a[i] = neibor[last][0];
used[a[i]] = true;
}
else if (!used[neibor[last][1]]){
a[i] = neibor[last][1];
used[a[i]] = true;
}
else {
cout << -1 << endl;
return 0;
}
}
if (neibor[1][0] != a[size] && neibor[1][1] != a[size]){
cout << -1 << endl;
return 0;
}
go();
return 0;
}0
回复 3516发表于2014-07-30 08:59
include<stdio.h>include<string.h>
int data[50001][2],shi[50001],a[50001];
int main()
{
int n,i,j,qian,hou; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d%d",&data[i][0],&data[i][1]); } a[1]=1;shi[a[1]]=1 for(i=2;i<=n;i++) { qian=data[a[i-1]][0]; hou=data[a[i-1]][1]; if(shi[qian]==0) { a[i]=qian; shi[qian]=1; } else if(shi[hou]==0) { a[i]=hou; shi[hou]=1; } else { printf("-1"); return 0; } } int temp=0,max=0; memset(shi,0,sizeof(shi)); for(i=1;i<=n;i++) { temp=(n+a[i]-i+1)%n; shi[temp]++; } for(i=0;i<n;i++) { if(max<shi[i]) { max=shi[i]; } } memset(shi,0,sizeof(shi)); for(i=1;i<=n;i++) { temp=(n+a[n-i+1]-i+1)%n; shi[temp]++;
}
for(i=0;i<n;i++)
{
if(max<shi[i])max=shi[i];
}
printf("%d",n-max);
}0
回复 S.Y.F发表于2013-08-31 14:04
题解
1111111129回复于2014-08-13 11:52
orzorzorz0
回复 S.Y.F发表于2013-07-29 16:55
从10、到30、到100。。。。。。
题解:http://blog.163.com/syf_light_feather/blog/static/223755067201362945326756/0
回复 vcvycy发表于2013-06-30 00:56
20 30 40 50 70 分都有~泪流满面.
Accepted100
772 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:55:05
Wrong Answer70
613 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:53:24
Wrong Answer70
686 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:45:35
Wrong Answer70
856 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:42:12
Wrong Answer70
803 2P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:37:26
Wrong Answer70
882 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:22:39
Wrong Answer70
1145 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:20:30
Wrong Answer10
733 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:11:30
Wrong Answer50
723 1P1008 篝火晚会
vcvycy Pascal 2013-06-30 00:04:20
Wrong Answer50
781 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:55:49
Wrong Answer40
656 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:49:49
Wrong Answer40
758 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:44:00
Time Exceeded30
7160 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:38:22
Time Exceeded20
7135 1P1008 篝火晚会
vcvycy Pascal 2013-06-29 23:35:080
回复 SEX丶Elope发表于2013-02-16 10:10
点击查看程序源码+详细题解
cuichen回复于2014-09-09 09:24
怎么又是你??你有什么企图?骗访问量???垃圾!0
回复 qyjubriskxp发表于2010-07-09 21:31
再一次体会到c++流的悲剧,秒杀和3s原来只是输入方式的不同,杯具~~
yuyilahanbao回复于2014-01-24 11:47
从c转到c++第一次不AC(除去忘记把语言有c改为c++的)就是因为c++输入输出的问题
从那次起,我的c++的输入都是用scanf和printf了
因为
保险
安全
我记不清cin是<<还是>>
printf和scanf相对更灵活
....0
回复 slm发表于2010-03-16 18:27
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
嘿嘿0
回复 superyoi发表于2009-11-10 11:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
superyoi killed p1008 with a headshot by awp
0
回复 200853349发表于2009-11-10 10:49
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
当我看到众位神牛打出“置换群”三个字后,我在黑书百度GOOGLE维基百科逛了得有一个半小时多然后回来AC了。。。
思路和strini神牛的基本一样。
0
回复 sinb发表于2009-11-09 13:02
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
其实很简单,不要想复杂了,先是想办法构成,然后用置换群的方法即可ac。0
回复 香蕉派发表于2009-11-06 11:29
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
虽然不懂什么叫置换群,但是思路还是很清晰的。。0
回复 赏金神侠PPF发表于2009-11-05 11:45
一星星纪念~0
回复 strini发表于2009-10-30 22:11
根据群论原理,任何置换群都可以分解为若干个循环节。显然,这道题目就是冲着这点来的。因为如果某循环的长度为L,那么本题中只需要代价为L的操作。注意,这里的L!=1,这是因为只有一个人的循环节不需要任何代价的操作。到这里才只能拿三十分,因为圈是可以旋转的,常规方法需要O(n^2)才能解决。不妨这里以编号为1的人为基准,定义每个人到自己应该所在位置的距离。距离不超过n-1。可以通过最大值来寻找能在自己位置上的最多的人数(因为距离为x的人在旋转x次后转到自己的位置上),那么在比较好的情况下,可以优化到O(n)。TIME: 1H
SUBMIT:
1 70 Error: 发现希望相邻是不精确的,于是改了个搜索方向。(以为题目给定的是按照左右方向,白书说过不能“假定”!)。
2 90 Error: 终于明白要取两个搜索方向的最大值。
3 Accepted.
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 skykey发表于2009-10-29 17:58
#include<iostream>
using namespace std;
int n;
int a[50001],b[50001],c[50001];
int aim[50001];
void G_MAP()
{
bool mark[50001]={false};
int p=1,r=1;
while(p<=n)
{
aim[p]=r;mark[r]=true;p++;
if(!mark[a[r]])r=a[r];
else if(!mark[b[r]])r=b[r];
else if(p<=n){cout<<-1;exit(0);}
}
}
int COMPULATE()
{
int max=0;
int t;
int record[2][50001];
for(int i=1;i<=n;i++)record[0][i]=record[1][i]=0;
for(int i=1;i<=n;i++)
{
if((t=aim[i]-i)<0)t+=n;
record[0][t]++;
if(record[0][t]>max)max=record[0][t];
if((t=aim[i]-(n+1-i))<0)t+=n;
record[1][t]++;
if (record[1][t]>max)max=record[1][t];
}
return max;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{scanf("%d%d",&a[i],&b[i]);c[a[i]]++;c[b[i]]++;}
for(int i=1;i<=n;i++)if(c[i]!=2){cout<<-1;return 0;}G_MAP();
int T=COMPULATE();
cout<<n-T;
}0
回复 song19931218发表于2009-10-27 20:11
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
考虑两种情形(貌似这两种情形很像,但又真的不同,后来才想起,在化学的手性碳原子那部分遇到过类似情况。。。)
然后就是运用置换群的知识0
回复 Aries_C发表于2009-10-25 08:24
正反两遍...两遍...<幽幽的声音飘远..>不然就是70分啊...
不看题解的情况下竟然自己想到了...
记得以前老师给我们做过这题的..细节什么的现在做又忘记了..唉..
0
回复 国防安全员001发表于2009-10-21 22:00
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1701人
提交 4835次
通过率 35%
难度 3题目表述有问题。。
0
回复 liubosen发表于2009-10-21 21:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
yaaaayyayayyayayayayayayayayayayayayayayayyaayayayayayayyaayayayay
var
n,max,i:longint;
a,b,c,d:array[0..50001] of longint;
begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
c[1]:=1;
c[2]:=a[1];
for i:=3 to n do
if c=a[c] then c[i]:=b[c]
else
if c=b[c] then c[i]:=a[c]
else begin
writeln(-1);
halt
end;
if c[n]<>b[1] then
begin
writeln(-1);
halt
end;
fillchar(d,sizeof(d),0);
for i:=1 to n do
inc(d[(c[i]-i+n)mod n]);
for i:=0 to n-1 do
if d[i]>max then max:=d[i];
fillchar(d,sizeof(d),0);
for i:=1 to n do
inc(d[(c[i]+i-1)mod n]);
for i:=0 to n-1 do
if d[i]>max then max:=d[i];
writeln(n-max);
end.0
回复 lishunzhi发表于2009-10-21 00:11
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
置换群,但建环是重点0
回复 zebra发表于2009-10-03 09:48
#include <iostream>
#include <cassert>
using namespace std;
long N,seq[50001],p=1;
class
{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2)
{
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2)
return true;
return false;
}
public:
bool AddE(long v1,long v2)
{
if(isnbr(v1,v2))
return true;
else
if(nbr[v1][0]==2||nbr[v2][0]==2)
return false;
else
{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i)
{
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++)
{
if(!flag[nbr[i][j]])
{
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve()
{
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N;
b=seq[i]-(N+1-i);
if(b<0) b+=N;
if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main()
{
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++)
{
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2))
{
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
system("pause");
return 0;
}0
回复 -117-Join发表于2009-09-18 21:29
哪位大牛帮忙看看我错哪里了
它只得90分
program fire;
type
arr=record
l,r:longint;
end;
var
num:array[1..50000]of longint;
a:array[1..50000]of arr;
b:array[1..50000]of longint;
i,k,j,n:longint;
begin
readln(n);
for i:=1 to n do
readln(a[i].l,a[i].r);
b[1]:=1;
b[n]:=a[1].l;
if a[b[n]].l=b[1]then b[n-1]:=a[b[n]].r
else b[n-1]:=a[b[n]].l;
i:=n-1;
b[2]:=a[1].r;
j:=2;
while j<=i do
begin
if b<>a[b[i]].l then b:=a[b[i]].l
else b:=a[b[i]].r;
dec(i);
if b[j-1]<>a[b[j]].r then b[j+1]:=a[b[j]].r
else b[j+1]:=a[b[j]].l;
inc(j);
end;
for i:=2 to n-1 do
if(b<>a[b[i]].r)and(b<>a[b[i]].l)or(b<>a[b[i]].r)and(b<>a[b[i]].l)then
begin
write(-1);
halt
end;
if(b[n]<>a[b[1]].l)and(b[n]<>a[b[1]].r)or(b[2]<>a[b[1]].l)and(b[2]<>a[b[1]].r)or(b[1]<>a[b[n]].l)and(b[1]<>a[b[n]].r)or(b[n-1]<>a[b[n]].l)and(b[n-1]<>a[b[n]].r)then
begin
write(-1);
halt
end;
num[0]:=0;
for i:=1 to n do
begin
a[b[i]].l:=i;
num[i]:=0;
end;
for i:=1 to n do
if a[i].l-i>=0 then inc(num[a[i].l-i])
else inc(num[a[i].l-i+n]);
j:=0;
for i:=0 to n do
if num[i]>j then j:=num[i];
write(n-j);
end.
写的有点长0
回复 fs302发表于2009-09-17 20:13
分析:学一个好思想:正难则反!由顺序到乱序我们很难快速找到,但是我们知道如何从乱序变为顺序!解决本题利用了组合数学中置换群的思想。从第一个人处断开,将圆环的问题转化为序列的问题。如果可以,求出目标序列。求出目标序列复杂度O(n).
求出目标序列右移0至n-1位置时,不需要移动的人数。将目标序列反转,再求出目标序列右移0至n-1位置时,不需要移动的人数。求不需要移动的人数最大等价于求需要移动的人数最小。复杂度O(n)。
更详细的说:
引进“相对有序”这个概念,当两个人满足C[j]-C[i]==j-i时,两个相对有序。
题目要求最小的总代价,但是我们可以考虑倒过来想,要求最小的总代价亦即求最多有多少人不用移动,亦即相对有序。
然后我们引进一个辅助变量T=C-I,{C-I>=0},T=C[i]-I+N,{C[i]-I<0},那么这个T[i]有什么意义呢?我们知道初始状态的编号是1-N,而目标状态是C[1]-C[N],那么C-I便是从目标状态到初始状态顺时针所要移动的距离,那么如果那么T值相等的两个同学则是相对有序的,亦即不用移动,我们只要找出最大的T然后N-Max(T)就是得到的结果,但是这样还不够,因为刚刚那样只是顺时针所要移动的距离,我们还要计算逆时针的到的结果,从顺时针和逆时针中找到最大的T,然后N-Max(T)才能够是正确结果.0
回复 maxint64发表于2009-09-01 21:33
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
先是物理大发了——以为 b1,b2...bm是连续的
看了牛们的题解 一次ac :)0
回复 柔情使者发表于2009-08-20 15:44
第一遍做的时候没有看题解,自己测了好几遍总是60分,看了n多大牛的解释才恍然大悟,竟然要正反两遍!!!唉,幸亏咱有测试数据,否则我可就惨了...
O(n)的求目标队列算法,都说是冒泡排序,我没看出来,倒是有点像。0
回复 maxiem发表于2009-08-18 20:55
物理自重啊,嘿嘿。
注意要正反两遍哦~
9MS?
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 9ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:9ms
(好像那个冒泡是口胡,大家不要被那个蒙了
program fire;
var
st:array [1..50000,1..2] of longint;
k,final:array [0..50000] of longint;
ex:array [1..50000] of boolean;
p,max,i,n:longint;
begin
fillchar (st,sizeof(st),0);
fillchar (ex,sizeof(ex),0);
fillchar (final,sizeof(final),0);
fillchar (k,sizeof(k),0);
readln (n);
for i:=1 to n do readln (st,st);
final[1]:=1;p:=2;ex[1]:=true;
for i:=1 to n do begin
if ex[st[final[i],1]]=false then begin
final[p]:=st[final[i],1];
ex[st[final[i],1]]:=true;
inc(p);
end
else if ex[st[final[i],2]]=false then begin
final[p]:=st[final[i],2];
ex[st[final[i],2]]:=true;
inc(p);
end;
end;
if p-1<>n then begin
writeln (-1);
halt;
end;
max:=0;
for i:=1 to n do if final[i]>=i then inc(k[final[i]-i]) else inc(k[n-i+final[i]]);
for i:=0 to n-1 do if k[i]>max then max:=k[i];
fillchar (k,sizeof(k),0);
for i:=n downto 1 do if final[i]>=n-i+1 then inc(k[final[i]-n+i-1]) else inc(k[final[i]+i-1]);
for i:=0 to n -1 do if k[i]>max then max:=k[i];
writeln (n-max);
end.0
回复 suning发表于2009-08-14 09:43
啊呜~
一年前误解了题意~
一年后理解了题意~
然后就是1次美妙的ACPS:[误]解[理]解~~~[物理]?
0
回复 fengwuliu发表于2009-08-13 17:20
lgxcgd说的太对了!太感谢了55550
回复 Matt发表于2009-08-11 22:28
NOIP也会考高等数学...由于原图是环,所以置换群可表示为一次循环。作差是个好方法。
但求冒泡排序是怎么作的
0
回复 3830372发表于2009-08-11 21:28
Flag Accepted
题号 P1008
类型(?) 模拟
通过 1504人
提交 4282次
通过率 35%
难度 3提交 讨论 题解 状态
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 尖端才子发表于2009-08-11 11:14
纪念一下……第1500个AC……Flag Accepted
题号 P1008
类型(?) 模拟
通过 1500人
提交 4274次
通过率 35%
难度 3编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 SecretAgent发表于2009-08-10 14:02
置换群是正解编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 yangbei发表于2009-08-07 14:57
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 338ms
├ 测试数据 05:答案正确... 322ms
├ 测试数据 06:答案正确... 306ms
├ 测试数据 07:答案正确... 338ms
├ 测试数据 08:答案正确... 338ms
├ 测试数据 09:答案正确... 322ms├ 测试数据 10:答案正确... 306ms
Accepted 有效得分:100 有效耗时:2270ms
算镜像时偷了点懒,不过也算一遍AC了
0
回复 ja_son发表于2009-08-06 15:44
a:拆环成队,寻求目标队列。
b:b1,b2...bm不是连续的,而且是任意的。只要有成立目标队列,与原来的队列相匹配就可以知道有多少(设为n个)需要移动位置,则代价就是n。
c:目标队列有多种情况,可以反转,也可以左右移动。0
回复 1s发表于2009-08-03 17:56
如对本题有疑问可以参看我的题解:
http://xujieqi.blog.hexun.com/35722312_d.html0
回复 DMKaplony发表于2009-07-30 15:15
当时的时间限制好像是2s。。有个题解说把1定为第一项然后进行冒泡排序。。不过这里是1s 啊。。。也行只有置换群了吧。0
回复 xusc_2009发表于2009-07-28 14:30
看不懂,只好搁浅
什么时候想清楚了再做0
回复 董发表于2009-07-24 19:11
program p1008;
var i,n,k,j,sum1,sum2,ans,max:longint;
a,b,w,d,c:array[0..50005] of longint;begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
w[1]:=1; w[2]:=a[w[1]];
k:=1;repeat
inc(k);
if w[k-1]=a[w[k]] then w[k+1]:=b[w[k]]
else if w[k-1]=b[w[k]] then w[k+1]:=a[w[k]]
else begin
writeln(-1);
exit;
end;
until k=n;
if w[n+1]<>w[1] then
begin
writeln(-1);
exit;
end;for i:=1 to n do
begin
a[i]:=w[i]-i;
b[i]:=w[n-i+1]-i;
if a[i]<0 then a[i]:=a[i]+n;
if b[i]<0 then b[i]:=b[i]+n;
inc(c[a[i]]);
inc(d[b[i]]);
end;
for i:=0 to n-1 do
begin
if ans<c[i] then ans:=c[i];
if ans<d[i] then ans:=d[i];
end;
writeln(n-ans);
end.0
回复 我飞发表于2009-07-23 21:00
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 93狒狒发表于2009-07-23 20:59
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
秒杀......
0
回复 fjxmlhx发表于2009-07-22 13:15
置换群,做2n次,顺时针和逆时针.
对于一个置换,最小操作费用是所有循环长度的和.因此实际上是找出2n个置换中哪个置换循环长度为1的数量最多.0
回复 340508965发表于2009-07-21 15:01
⊙﹏⊙b汗
不知道的以为这是数学竞赛......
...
我的数论与图论可以说脑袋里空白一片.........
怎么办,我的竞赛啊
........算了 看了题解 大家写的
总算弄懂这道题了
先前以为b1,b2,b3..bm是连续的
没想到是任意的!!!!!!!!!诶 叹悲歌未切 为撼奈何编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
总算AC了
program p1008;
var i,n,k,j,sum1,sum2,ans,max:longint;
a,b,w,d,c:array[0..50005] of longint;begin
readln(n);
for i:=1 to n do
readln(a[i],b[i]);
w[1]:=1; w[2]:=a[w[1]];
k:=1;repeat
inc(k);
if w[k-1]=a[w[k]] then w[k+1]:=b[w[k]]
else if w[k-1]=b[w[k]] then w[k+1]:=a[w[k]]
else begin
writeln(-1);
exit;
end;
until k=n;
if w[n+1]<>w[1] then
begin
writeln(-1);
exit;
end;for i:=1 to n do
begin
a[i]:=w[i]-i;
b[i]:=w[n-i+1]-i;
if a[i]<0 then a[i]:=a[i]+n;
if b[i]<0 then b[i]:=b[i]+n;
inc(c[a[i]]);
inc(d[b[i]]);
end;
for i:=0 to n-1 do
begin
if ans<c[i] then ans:=c[i];
if ans<d[i] then ans:=d[i];
end;
writeln(n-ans);
end.0
回复 zsy90943发表于2009-07-18 00:51
构造巧妙、、看来还是要学好数论和图论额、、、、0
回复 POM无敌牛B发表于2009-07-16 11:47
编译通过...
├ 测试数据 01:运行超时...
├ 测试数据 02:运行超时...
├ 测试数据 03:运行超时...
├ 测试数据 04:运行超时...
├ 测试数据 05:运行超时...
├ 测试数据 06:运行超时...
├ 测试数据 07:运行超时...
├ 测试数据 08:运行超时...
├ 测试数据 09:运行超时...├ 测试数据 10:运行超时...
Unaccepted 有效得分:0 有效耗时:0ms
无奈 哪位哥哥救救我0
回复 yxy发表于2009-06-16 18:16
把置换解释成度为2图,真有才.
求出序列,正反分别做一次差就行了.0
回复 sxpeter发表于2009-06-14 16:56
讲建环吧。数组w表示环,我用的是一种类似并查集的方法。
begin
read(n);
for i:=1 to n do read(a[i],b[i]);
t:=2;w[1]:=1;w[2]:=a[1];
while true do begin
if a[w[t]]<>w[t-1]then w[t+1]:=a[w[t]]//是否在左边
else if b[w[t]]<>w[t-1]then w[t+1]:=b[w[t]]//是否在右边
else begin writeln(-1);halt;end;//失败判断
inc(t);
if t>n then break;
end;
if w[n+1]<>w[1]then begin writeln(-1);halt;end;//本句一定要加!!!!!!
end.0
回复 lgxcgd发表于2009-05-17 20:24
首先把这个圈看做一个图,每个同学看做一个顶点。因为要形成环,所以每个顶点的度必须为2。如果存在度数不为2的顶点,那么整个图无法构成一个环,即“无论怎么调整都不能符合每个同学的愿望”输出-1。
如果是一个环,那么就遍历图,生成以第1个顶点为开头的序列。现在就要求出最小移动的代价。
在理解题意所述的调整方式中,要注意实际上就是把M个在错误位置上的人移动到正确的位置上,代价为M。一次下令移动即可。
假如生成的目标序列为1,5,3,2,4。我们现在就需要比较它和初始状态1,2,3,4,5,看有几个人离开了原来的位置。但这个序列实际代表的是一个环,而且方向正反有两种,就需要把初始序列正反分别转N次,和得到的序列比较,看其中最少有几个位置上的人编号不相同,就得到了我们要求的最小代价。
上述方法有大量冗余。但可以发现转来转去不管怎么转,任意两个人之间的相对位置关系在这过程中都不会变。于是想到做差,如果差小于0则加上N。
1 5 3 2 4
- 1 2 3 4 5
0 3 0 3 4
这表示序列1,5,3,2,4不转动时1,3两个人在原来的位置上,转动3个位置后5和2两个人在原来的位置上,转动4个位置后只有4一个人会在原来的位置上。这就是说,1,5,3,2,4与1,2,3,4,5在旋转后最多有2个位置上的人编号相同,即最少有3个位置上的人编号不相同。同理要反转再求一次。记录每个不同的差值的个数,取其最大值P,即不调换次数最大的。结果N-P就是调换次数最小的。
0
回复 src250发表于2009-05-14 08:27
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
切记:重新构图时一定要对数组清空!我的第一次只有50分,就是这个原因!
0
回复 love19960108发表于2009-04-26 17:59
这题可以用C++这样做么??
#include <iostream>
#include <cassert>
using namespace std;
long N,seq[50001],p=1;
class{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2){
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2) return true;
return false;
}
public:
bool AddE(long v1,long v2){
if(isnbr(v1,v2)) return true;
else if(nbr[v1][0]==2||nbr[v2][0]==2) return false;
else{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i){
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++){
if(!flag[nbr[i][j]]){
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve(){
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N;
b=seq[i]-(N+1-i);
if(b<0) b+=N;
if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main(){
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++){
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2)){
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
return 0;
}0
回复 voyagec2发表于2009-03-18 15:53
难理解,不过算法很精妙0
回复 pRoevollove发表于2009-02-25 23:49
天,把(p[i]-i+n)mod n理所当然地打成了abs(p[i]-i)
结果一直50分……还一直以为自己构造错了……ps 我可以过楼下的范例哦
0
回复 ufo172849z发表于2009-01-24 23:05
ms楼下的程序不能处理这种反例(测试数据还是不够强啊)
6
2 3
1 3
1 2
5 6
4 6
4 5
应该输出-1的吧?因为是两个环var a,b:array[0..50000]of longint;
c:array[0..50000,1..2]of longint;
d:array[0..50000]of boolean;
i,j,k,m,n,max:longint;
can:boolean;begin
readln(n);
for i:=1 to n do
readln(c,c);
b[0]:=c[1,1]; b[n]:=c[1,1];
fillchar(d,sizeof(d),0);
k:=1;
can:=true;
for i:=1 to n-1 do
begin
if d[k] then can:=false;
b[i]:=k; d[k]:=true;
if b=c[k,1] then k:=c[k,2]
else if b=c[k,2] then k:=c[k,1]
else can:=false;
if not can then break;
end;
if can then
if b[n]<>k then can:=false;
if can then
begin
max:=-1;
fillchar(a,sizeof(a),0);
for i:=1 to n do
inc(a[(b[i]-i+n) mod n]);
for i:=0 to n-1 do
if a[i]>max then max:=a[i];
fillchar(a,sizeof(a),0);
for i:=1 to n do
inc(a[(b[n-i+1]-i+n)mod n]);
for i:=1 to n-1 do
if a[i]>max then max:=a[i];
writeln(n-max);
end
else
writeln(-1);
end.0
回复 tangdongjian发表于2009-01-23 22:17
我在做镜像时把原先max直接覆盖上了,注意0
回复 永恒888发表于2009-10-26 22:50
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 tangkunjie发表于2009-06-04 19:50
挺烦人的题目0
回复 ykspeter发表于2008-11-13 20:32
program fire(input,output);
var
n,i,j,k,max,v:longint;
a:array[0..100000,1..2] of longint;
b,c:array[0..100000] of longint;
begin
readln(n);
for i:=1 to n do readln(a,a);
for i:=1 to n do
begin
k:=0;
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if (k=4) or (k=3)
then begin
writeln('-1');
exit
end
end;
b[1]:=1;i:=2;k:=a[1,1];j:=1;
repeat
b[i]:=k;
inc(i);
v:=k;
if a[k,1]<>j
then k:=a[k,1]
else k:=a[k,2];
j:=v;
until i=n+1;
fillchar(c,sizeof(c),0);
for i:=1 to n do inc(c[(b[i]-i+n)mod n]);
for i:=0 to n-1 do
if c[i]>max
then max:=c[i];
fillchar(c,sizeof(c),0);max:=0;
for i:=1 to n do inc(c[(b[n-i+1]-i+n)mod n]);
for i:=n-1 downto 0 do
if c[i]>max
then max:=c[i];
writeln(n-max);
end.0
回复 getuojian发表于2008-11-10 13:38
#include<stdio.h>
#include<memory.h>const int maxn=50010;
int n;
int f[maxn][2];
int goal[maxn];
int ans=maxn;
int hash[maxn];bool SET_ORI(){
bool flag[maxn];
memset(flag, true, sizeof(flag));
goal[1]=1; flag[1]=false;
for (int i=1; i<=n-1; i++){
if (flag[f[goal[i]][0]]){
goal=f[goal[i]][0];
flag[f[goal[i]][0]]=false;
continue;
}
if (flag[f[goal[i]][1]]){
goal=f[goal[i]][1];
flag[f[goal[i]][1]]=false;
continue;
}
return false;
}
if ((goal[n]!=f[1][0]) && (goal[n]!=f[1][1]))
return false;
return true;
}
int SWAP(int i, int j){
int t=goal[i];
goal[i]=goal[j];
goal[j]=t;
return 0;
}int min(int i, int j){
return i>j?j:i;
}
int HASH(){
for(int i=1; i<=n; i++)
hash[i]=goal[i]-i+n;
return 0;
}int CALC(){
int temp[maxn*2], back=0;
memset(temp, 0, sizeof(temp));
for (int i=1; i<=n; i++)
temp[hash[i]%n]++;
for (int i=1; i<=2*n-1; i++)
if (temp[i] > back)
back=temp[i];
return back;
}int main(){
freopen("fire.in", "r", stdin);
freopen("fire.out", "w", stdout);
scanf("%d", &n);
for (int i=1; i<=n; i++)
scanf("%d %d", &f[i][0], &f[i][1]);
if (!SET_ORI()){
printf("-1");
return 0;
}
//forward
HASH();
ans=min(ans, n-CALC());
//backward
for (int i=1; i<=n/2; i++)
SWAP(i,n-i+1);
HASH();
ans=min(ans, n-CALC());printf("%d", ans);
return 0;
}0
回复 IVORY发表于2008-11-06 10:46
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
CHEAT的...
0
回复 storey p发表于2008-11-05 14:19
回447389831:
exit换成halt0
回复 FenXy发表于2008-11-04 08:28
艺术p2450
回复 hlq发表于2008-11-01 14:31
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms求不在位置上的人数
a【i】 第i位上的同学编号
for i:=1 to n do
begin
inc(b[(a[i]-i+n) mod n])
end;
max:=0;
for i:=0 to n-1 do
if b[i]>max then max:=b[i];
fillchar(b,sizeof(b),0);
for i:=1 to n do
begin
inc(b[(a[i]-(n-i+1)+n)mod n]);//对称
end;
for i:=0 to n-1 do
if b[i]>max then max:=b[i];0
回复 Will~骷髅发表于2008-10-30 21:37
编译通过...
├ 测试数据 01:运行超时...
├ 测试数据 02:运行超时...
├ 测试数据 03:运行时错误...|错误号: -1073741819
├ 测试数据 04:运行时错误...|错误号: -1073741819
├ 测试数据 05:运行时错误...|错误号: -1073741819
├ 测试数据 06:运行时错误...|错误号: -1073741819
├ 测试数据 07:运行时错误...|错误号: -1073741819
├ 测试数据 08:运行时错误...|错误号: -1073741819
├ 测试数据 09:运行时错误...|错误号: -1073741819├ 测试数据 10:运行时错误...|错误号: -1073741819
Unaccepted 有效得分:0 有效耗时:0ms
怎么会这样???
0
回复 悲伤逆流成河发表于2008-10-28 22:13
#include <iostream>
#include <fstream>
using namespace std ;int hash[50001];
int n , i , j , t , maxs(0) ;inline void HASH ( int e[] )
{
for ( i = 1 ; i <= n ; i++ )
{
e[i] -= i ;
if ( e[i] < 0 ) e[i] += n ;
hash[e[i]]++ ;
}
for ( i = 0 ; i < 50001 ; i++ )
if ( maxs < hash[i] ) maxs = hash[i] ;
}int main(){
ifstream fin ("fire.in") ;
ofstream fout ("fire.out") ;fin >> n ;
int e[n+1] , h[n+1][2] , e2[n+1];
bool f[n+1] ;
for ( i = 1 ; i <= n ; i++ )
{
f[i] = false ;
fin >> h[i][0] >> h[i][1] ;
}
e[1] = 1 ;
f[1] = true ;
for ( i = 2 ; i <= n ; i++ )
{
if ( e < 0 ) { fout << -1 << endl ; exit(0) ; }
if ( !f [ h[ e ][0] ] ) e[i] = h[ e ][0] ;
if ( !f [ h[ e ][1] ] ) e[i] = h[ e ][1] ;
f[ e[i] ] = true ;
}
for ( i = 1 , j = n ; i <= n ; i++,j-- ) e2[j] = e[i] ;
HASH ( e ) ;
memset ( hash , 0 , sizeof ( hash ) ) ;
HASH ( e2 ) ;
fout << n - maxs << endl ;
}0
回复 evelynhe发表于2008-10-26 16:31
“置换群思想...今天刚明白...先构造新数列(要构造两次,否则只有70分),然后向右计算相对位置差,然后累加记录数组,然后用N减去相对位置差累加值最大的,就是答案... ”
这是真的
0
回复 true1023发表于2008-10-25 09:32
置换群的基本概念
利用原序列和目标序列每个元素的绝对位置差来求出原序列每个元素对于目标序列的相对位置,找相对位置相同的最多的元素数,用总元素数减去它即为结果。0
回复 447389831发表于2008-10-21 09:45
program fire(input,output);
var
n,i,j,k,max,v:longint;
a:array[0..100000,1..2] of longint;
b,c:array[0..100000] of longint;
begin
readln(n);
for i:=1 to n do readln(a,a);
for i:=1 to n do
begin
k:=0;
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if a[a,1]<>i then inc(k);
if a[a,2]<>i then inc(k);
if (k=4) or (k=3)
then begin
writeln('-1');
exit
end
end;
b[1]:=1;i:=2;k:=a[1,1];j:=1;
repeat
b[i]:=k;
inc(i);
v:=k;
if a[k,1]<>j
then k:=a[k,1]
else k:=a[k,2];
j:=v;
until i=n+1;
fillchar(c,sizeof(c),0);
for i:=1 to n do inc(c[(b[i]-i+n)mod n]);
for i:=0 to n-1 do
if c[i]>max
then max:=c[i];
fillchar(c,sizeof(c),0);max:=0;
for i:=1 to n do inc(c[(b[n-i+1]-i+n)mod n]);
for i:=n-1 downto 0 do
if c[i]>max
then max:=c[i];
writeln(n-max);
end.
90 分,牛人门帮看下把0
回复 cnfnje1发表于2008-10-17 18:12
置换群.....是什么?
readln(n);
for i:=1 to n do readln(a[i],b[i]);
c[1]:=1; c[2]:=a[1];
for i:=3 to n do if c=a[c] then c[i]:=b[c]
else if c=b[c] then c[i]:=a[c]
else begin writeln(-1); halt end;
if c[n]<>b[1] then begin writeln(-1); halt end;
fillchar(d,sizeof(d),0);
for i:=1 to n do inc(d[(c[i]-i+n)mod n]);
for i:=0 to n-1 do if d[i]>m then m:=d[i];
fillchar(d,sizeof(d),0);
for i:=1 to n do inc(d[(c[i]+i-1)mod n]);
for i:=0 to n-1 do if d[i]>m then m:=d[i];
writeln(n-m);
是么?0
回复 lyrics发表于2008-10-12 19:55
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
技巧性比较强吧,楼下不必构造2次,计算时从头至尾算一次,再倒过来算一次就行了
0
回复 LV.唱响发表于2008-10-05 08:38
置换群思想...今天刚明白...先构造新数列(要构造两次,否则只有70分),然后向右计算相对位置差,然后累加记录数组,然后用N减去相对位置差累加值最大的,就是答案...
0
回复 宇智波带波斯猫发表于2008-10-05 08:33
Flag Accepted
题号 P1008
类型(?) 其它
通过 1065人
提交 3000次
通过率 35%
难度 3第3000个提交的
0
回复 鸳鸯羡发表于2008-09-28 18:19
#include <iostream>
using namespace std ;int hash[50001];
int n , i , j , t , maxs(0) ;inline void HASH ( int e[] )
{
for ( i = 1 ; i <= n ; i++ )
{
e[i] -= i ;
if ( e[i] < 0 ) e[i] += n ;
hash[e[i]]++ ;
}
for ( i = 0 ; i < 50001 ; i++ )
if ( maxs < hash[i] ) maxs = hash[i] ;
}int main(){
cin >> n ;
int e[n+1] , h[n+1][2] , e2[n+1];
bool f[n+1] ;
for ( i = 1 ; i <= n ; i++ )
{
f[i] = false ;
cin >> h[i][0] >> h[i][1] ;
}
e[1] = 1 ;
f[1] = true ;
for ( i = 2 ; i <= n ; i++ )
{
if ( e < 0 ) { cout << -1 << endl ; exit(0) ; }
if ( !f [ h[ e ][0] ] ) e[i] = h[ e ][0] ;
if ( !f [ h[ e ][1] ] ) e[i] = h[ e ][1] ;
f[ e[i] ] = true ;
}
for ( i = 1 , j = n ; i <= n ; i++,j-- ) e2[j] = e[i] ;
HASH ( e ) ;
memset ( hash , 0 , sizeof ( hash ) ) ;
HASH ( e2 ) ;
cout << n - maxs << endl ;
}80分
0
回复 月光疾风发表于2008-09-25 13:03
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
纪念我第200次提交!过第79题。。。。0
回复 ghostplant发表于2008-09-20 19:48
#include <iostream>
#include <fstream>
#include <cassert>
using namespace std;
long N,seq[50001],p=1;
class{
private:
long nbr[50001][3];
bool flag[50001];
bool isnbr(long v1,long v2){
for(int i=1;i<=nbr[v1][0];i++)
if(nbr[v1][i]==v2) return true;
return false;
}
public:
bool AddE(long v1,long v2){
if(isnbr(v1,v2)) return true;
else if(nbr[v1][0]==2||nbr[v2][0]==2) return false;
else{
nbr[v1][++nbr[v1][0]]=v2;
nbr[v2][++nbr[v2][0]]=v1;
return true;
}
}
void dfs(long i){
assert(!flag[i]);
flag[i]=true,seq[p++]=i;
for(int j=1;j<=nbr[i][0];j++){
if(!flag[nbr[i][j]]){
dfs(nbr[i][j]);
break;
}
}
}
}G;
long solve(void){
long cnt1[50001]={0},cnt2[50001]={0},ans=0;
for(int i=1,a,b;i<=N;i++){
a=seq[i]-i;
if(a<0) a+=N;
b=seq[i]-(N+1-i);
if(b<0) b+=N;
if(++cnt1[a]>ans) ans=cnt1[a];
if(++cnt2>ans) ans=cnt2;
}
return N-ans;
}
int main(){
cin >> N;
for(int i=1,nbr1,nbr2;i<=N;i++){
cin >> nbr1 >> nbr2;
if(!G.AddE(i,nbr1)||!G.AddE(i,nbr2)){
cout << -1 << endl;
return 0;
}
}
G.dfs(1);
cout << solve() << endl;
return 0;
}0
回复 zzh19950802发表于2008-09-17 19:29
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案错误... ├ 标准行输出
├ 错误行输出
├ 测试数据 05:答案错误... ├ 标准行输出
├ 错误行输出
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 462ms
├ 测试数据 08:答案正确... 369ms
├ 测试数据 09:答案正确... 384ms
├ 测试数据 10:答案错误...程序输出比正确答案长
为什么我的程序不对?
#include <iostream>
using namespace std;
#define MAXN 50000
int man[MAXN+2][2];
int cercle[MAXN+2]={0,1};
int used[MAXN+2]={0};
int reduce[2][MAXN+2]={0};
int n;
int main()
{
long i,p,q=1,t;
int max=0;
cin>>n;
for (i=1;i<=n;i++) cin>>man[i][0]>>man[i][1];
p=man[q][1];
for (i=2;i<=n+1;i++)
{
if (man[q][1]==p)
{
p=q;
q=man[q][0];
}
else
{
if(man[q][0]!=p) break;
p=q;
q=man[q][1];
}
if(used[q]) break;
else used[q]=1;
cercle[i]=q;
}
if (i<=n+1) cout<<-1;
else
{
for (i=1;i<=n;i++)
{
if((t=cercle[i]-i)<0) t+=n;
reduce[0][t]++;
if (reduce[0][t]>max) max=reduce[0][t];
if ((t=cercle[i]-n+i-1)<0) t+=n;
if (reduce[1][t]>max) max=reduce[1][t];
}
cout<<n-max;
}
return 0;
}0
回复 liaorc发表于2008-09-16 17:56
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 cxy450090074发表于2008-09-04 13:34
oh no0
回复 Lost.G发表于2008-08-22 15:49
我在想``怎么样才能不看错这题呢0
回复 bonism发表于2008-08-14 21:30
时间复杂度O(N)。。。原来我一直把题意理解错。。。囧!!。。
关于“置换群”,请看LRJ的《算法艺术与信息学竞赛》P245那一小节,还是比较好理解的。
0
回复 lemon_cn发表于2008-08-08 15:55
热烈庆祝用pascal AC的第二题~
p.s.我是C++的~~0
回复 oipn4e2发表于2008-08-05 21:36
解决效率不高,但AC了。0
回复 notblack发表于2008-08-01 09:17
用距离来分类,统计在原位的最大人数,奇怪的是
b[1]:=1;
b[2]:=a[1,1];
b[n]:=a[1,2];建环的时候,上面的改成
b[1]:=1;
b[2]:=a[1,2];
b[n]:=a[1,1];最后一个点却过不了,太奇怪了.
0
回复 332404521发表于2008-07-14 13:53
对于初三刚刚中考完的我,要理解这题的意思是万万不能的。。。
看题解我知道了应该怎么做,但那不是我的,所以不做了。。。
哪天能证明出来那啥再来做0
回复 Sheeta发表于2007-11-14 15:45
好简单啊
直接贪啊
(P.S.置换群?什么东东...)0
回复 mingyueyucai发表于2007-11-09 21:22
我代码写了老长老长,结果还是只过了8个点,有没有搞错?
我想请问一下,我和大家的一样,先排列出目标状态.然后确定初始状态时使得最多的人在目标位置上,然后交换.但是得到的答案总是偏大一点.
然后我又把所有可以使最多的人在原位目标位置上的可能都尝试了一编(包括正反两个目标状态),结果还是只能过8个点,有2个点死都过不了!
我的算法有什么问题吗?0
回复 luanjiyang发表于2007-11-08 08:44
很委琐的说 我提交了8遍。。
0→0→10→10→10→10→70→AC- -||
0
回复 lonelycorn发表于2007-11-05 23:31
数论……好底歇的东西。0
回复 gamejifan发表于2007-11-04 11:15
这题的叙述,让我误会了一年多。tzkq……3q..要早知道是这种意思早就ac了这题。。显然没什么大意思,看过组合数学或者学过群论的都懂。。ms跟polya计数法那个循环的意思。。写的时候竟然因为交换的时候写错一个字母wa。我汗。
0
回复 Alexandria发表于2007-11-01 13:33
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
好强大的题啊,不看题解还真不会!
0
回复 clfhaha1234发表于2007-10-30 18:09
请问什么是置换群啊?可以讲讲吗?………………0
回复 rleepas发表于2007-10-30 13:18
楼下都是正解?
......0
回复 Ice_Msk发表于2007-10-18 20:35
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
什么是置换群?不知道。。。照样过。。。。
0
回复 junlonely发表于2007-10-18 20:13
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
0
回复 江南不才发表于2007-10-11 16:19
排序法这里会超时~~~~~
比赛的时间是2S~~
这里是1S~~
(_)0
回复 秒杀群众发表于2007-10-10 17:05
居然是置换群。。。
对了。。。什么是置换群...
上网查啊!!!0
回复 southstarj1发表于2007-10-02 18:50
思想:
置换群。(相关知识自己查)
对于一组数据,按各人的意愿排出一个序列,
如果无法排出,就输出-1。
再将环状序列变成链状,则这个目标序列为一个置换群,
与原序列(按1到n的一列)满足:
交换的最少人数等于目标序列与原序列不重合的人数。
因为总共有2n个目标序列(正反各n种),都算一遍就行了。步骤:
1. 读入数据;
2. 构造一个目标序列;
3. 统计该序列中元素位置与该元素在原序列位置的差值(同一方向)为i{i ∈ [0, n)}的元素个数;
4. 将该序列的反序统计一遍;
5. 从这些数据中选取一个最大的值max;
6. 输出n - max;注意:
构造目标序列时判断能否构造的条件;
统计一次差值的复杂度是O(n);
统计差值的目的是求与原序列最多的重合人数;0
回复 wangjin5发表于2007-09-19 22:38
好经典的题奥
确实有难度0
回复 the_melody发表于2007-09-03 17:58
Accepted 有效得分:100 有效耗时:0ms
好经典的题奥0
回复 richardxx发表于2007-08-22 17:36
下面程序是错的,不好意思,弄错地方了....0
回复 sm-star发表于2007-08-21 15:18
题目所求就是每次进行连续交换的人数总和,这样,一个看似复杂的题目就变的异常的简单了!0
回复 wasyyyy发表于2007-08-11 02:05
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms├ 测试数据 10:答案正确... 0ms
Accepted 有效得分:100 有效耗时:0ms
HOHO~~~看讨论的时候看到有人提到‘置换群’这个东西,突然想起来我刚买的一本组合数学上有这么一块东西,就拿过来看了。。。。
然后就出现上面的东西了。。。。置换群,本来想求轮换的,发现轮换比较多,还是找不参与交换的比较好记。。。。优化的方法。。。我看了下好象不只一个人讲过了。。。而且似乎我跟他们的都一样(没仔细看)所以就不说了。。。效率是O(n)的。。不用建环。
0
回复 angieqiu发表于2007-08-10 22:49
怎么判断建环失败啊?我的程序虽然AC但总觉得方法很傻0
回复 梦ぁ逍遥发表于2007-07-17 13:45
想到了用t[i]=b[i]-i表示环
却没想到镜像..十分感谢visister
让我从90分中挣扎出来...0
回复 visister发表于2007-06-01 00:12
首先明显地可以知道我们需要对于目标状态建立出一个环。如果无法建立这个环,那么结果一定是-1,当建立好环以后可以知道最小移动代价一定等于最少的不在目标位置上的人数。那么我们可以对目标环进行顺时针旋转1~n-1之中任意一个,答案就一定等于旋转中的不在自己位置上的人数最少的那样的环的状态。但是对于50000的数据,我们如果要将环旋转1~n-1次,那么总共加上判断不在自己位置上的人数时间复杂度为O(n^2),显然在限定时间内是无法出解的。因此我们进行逆向思维:不在自己位置上最少的人数就一定会等于总人数减去在自己位置上最多的人数(仔细想想),那么我们就将该问题转化为了求在自己的位置上最多的人数,这样一来,我们对初始目标环中每一个位置进行判断需要旋转多少次可以回到自己位置上,每一个人的选择都将映射到[0..n-1]的数组中,选取当中最大的情况就为所求,但是考虑到环可以反转,那么我们还需要将环再求一次镜像,就可以得到初始目标需要旋转多少次可以得到在自己位置上最多的人数的环的状态,最后通过总的人数减去它即为问题所求,时间复杂度为O(n);0
回复 pyh119发表于2006-11-16 20:11
哪个人不小心失火了找我啊!!!PS:我是安徽省芜湖市119接线员....
0
回复 maomingming发表于2006-11-06 18:40
考虑旋转后最多可能重合的情况,另要注意圈可以反过来0
回复 qian5发表于2006-09-30 21:35
直接输出‘-1’有一个点过0
回复 BambooLeaf发表于2006-09-26 18:17
见过的最牛最简单的方法……
将此题转换为冒泡排序,记录下所有交换的次数和两数间的距离,加上就行了……—__—|||
具体是这样的,我们反向思维,本来是要求一个有序数列求出成为无序数列的代价,现在我们把无序数列(即目标数列)进行冒泡排序,然后……就是这样……
看完之后,偶巨汗……0
回复 xcjzj发表于2006-09-26 17:18
每组数据确定两组相对位置关系,并且这两组互为镜像。
对于某一种排列方式,不在需要位置上的人数即为当前状态到目标状态的最小代价。
先找出其中一种排列方式。由于目标状态可以通过旋转而使得部分人的变化次数减少,所以找出每个人通过某一固定方向旋转到达目标位置的旋转次数。找到某一次数,使得拥有这个次数的人数最多。那么,通过旋转这一最多人拥有的次数,即可使得尽可能多的人不通过交换直接到达目标位置。于是,不拥有这一旋转次数的人数即为这一状态下的最小代价。
然后,用现在的目标状态找出其镜像状态,并且用上述方法再找一遍最小代价,与前面的结果比较,较小值即为答案。
另外,题目中会出现一些无解的情况:
1.某个人被“要”的次数多于两次,也就是说有多于两个的人想要与他(她)邻座,那么无解。
2.根据要求得出的目标状态为多于一个的环,也无解。0
回复 东邪歪刀发表于2006-07-28 17:27
提交了若干次……残念……0
回复 sugar发表于2006-07-28 16:26
这题比赛时真有人ac?
真不好想
为什么得开longint啊?0
回复 晶星发表于2006-07-25 13:29
排列本质不同的只有二种 正着和反着的
检验几个人不在位置上用数学方法:)模拟法超时的0
回复 tzkq发表于2006-07-23 04:37
注意别误解题意 b1,b2....bm并不指连续位置上的数0
回复 Coldwings发表于2006-01-26 09:21
可以用群论证明:如果有k个人不在自己的位置上,那么要且仅要k的代价,即可使这些人归位剩下的..很简单了吧...
0
回复 lemon_cn发表于2008-08-08 15:55
热烈庆祝用pascal AC的第二题~
p.s.我是C++的~~ -
-12013-02-16 10:10:32@