| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
Re:这题详细用什么方法做?In Reply To:Re:这题详细用什么方法做? Posted by:ccnujing at 2008-08-01 17:15:27 > 置换环...
/*
* poj3270.cpp
*
* Created on: 2011-7-20
* Author: will
* 群论--置换环--黑书P248
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using std::cout;
using std::endl;
int N,mi,ma,S;//S是循环个数
long long ans;
int a[10007],b[10007],K[10007],T[10007],ord[100007];//K是循环长度,T是每个循环最小数
int vis[10007];//vis[i]表示i在第几个循环当中
inline int min(int a,int b)
{
return a<b?a:b;
}
inline int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int temp;
memset(T,0x3f3f3f,sizeof(T));
mi=999999999;
scanf("%d",&N);
for(int i=1;i<=N;i++)
{
scanf("%d",&temp);
ord[temp]=i;
ans+=temp;
mi=min(temp,mi);
ma=max(temp,ma);
}
int now=0;
for(int i=0;i<=ma;i++)
if(ord[i])
{
a[++now]=ord[i];
b[now]=i;
}
for(int i=1;i<=N;i++)
{
if(!vis[i])
{
S++;
K[S]++;
T[S]=min(T[S],b[i]);
vis[i]=true;
now=a[i];
while(!vis[now])
{
//printf("now=%d\n",now);
K[S]++;
T[S]=min(T[S],b[now]);
vis[now]=true;
now=a[now];
}
}
}
//printf("S=%d\n",S);
for(int i=1;i<=S;i++)
{
ans+=min((K[i]-2)*T[i],T[i]+(K[i]+1)*mi);
}
cout<<ans<<endl;
return 0;
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator